Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F3767021
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
6 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/lib.rs b/src/lib.rs
index 6c4821d..f975350 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,11 +1,6 @@
#![feature(plugin)]
#![plugin(rocket_codegen)]
-#[macro_use]
-extern crate log;
-
-extern crate rocket_contrib;
-
pub mod app;
pub mod registry;
pub mod requests;
diff --git a/src/registry.rs b/src/registry.rs
index 1344409..790c628 100644
--- a/src/registry.rs
+++ b/src/registry.rs
@@ -1,222 +1,223 @@
use lazy_static::lazy_static;
+use log::error;
use regex::Regex;
use serde_derive::{Deserialize, Serialize};
use std::fs::{DirEntry, File, read_dir};
use std::io::{Read, Result as IOResult};
use std::path::Path;
/* -------------------------------------------------------------
Registry
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/// Represents a Docker registry
#[serde(rename_all = "camelCase")]
#[derive(Serialize, Deserialize, Clone)]
pub struct Registry {
#[serde(skip_serializing)]
pub directory: String,
pub repositories_count: i32
}
impl Registry {
const DEFAULT_LOCATION: &'static str = "/var/lib/registry";
pub fn new (directory: String) -> Self {
let mut registry = Registry {
directory,
repositories_count: 0,
};
registry.update_stats();
registry
}
pub fn with_default_location () -> Self {
Self::new(String::from(Self::DEFAULT_LOCATION))
}
pub fn update_stats (&mut self) {
self.repositories_count = self.count_repositories();
}
pub fn count_repositories (&self) -> i32 {
let path_name = self.get_repositories_path();
let path = Path::new(&path_name);
if path.exists() && path.is_dir() {
match count_subdirectories(path) {
Ok(n) => n as i32,
Err(e) => {
error!(target: "api", "Can't count registry directories: {}", e);
0
}
}
} else {
error!(target: "api",
"Registry path doesn't exist or isn't a directory: {}",
path_name);
0
}
}
pub fn get_repositories_path (&self) -> String {
format!("{}/docker/registry/v2/repositories", self.directory)
}
pub fn get_repository (&self, repository_name: &str) -> Option<Repository> {
if !Repository::is_valid_name(repository_name) {
return None
}
let path = Path::new(&self.get_repositories_path()).join(repository_name);
let directory = match path.as_path().to_str() {
Some(name) => String::from(name),
None => { return None; }
};
let mut repository = Repository {
directory,
name: String::from(repository_name),
tags: Vec::new(),
};
repository.update_tags();
Some(repository)
}
}
/* -------------------------------------------------------------
Repository
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/// Represents a repository from the Docker registry
#[serde(rename_all = "camelCase")]
#[derive(Serialize, Deserialize)]
pub struct Repository {
#[serde(skip_serializing)]
pub directory: String,
pub name: String,
pub tags: Vec<Tag>,
}
impl Repository {
pub fn exists(&self) -> bool {
let path = Path::new(&self.directory);
path.exists() && path.is_dir()
}
pub fn is_valid_name(name: &str) -> bool {
lazy_static! {
static ref RE: Regex = Regex::new("^/?[a-zA-Z0-9_-]+$").unwrap();
}
RE.is_match(name) && name.len() <= 30
}
pub fn update_tags(&mut self) {
let path = Path::new(&self.directory).join("_manifests/tags");
let tag_names = get_subdirectories_names(&path);
self.tags = tag_names.iter()
.map(|name| Tag {
name: name.clone(),
hash: self.get_hash_for_tag(&name).unwrap_or(String::new()),
})
.collect();
}
fn get_hash_for_tag(&self, tag_name: &str) -> IOResult<String> {
let mut buffer = String::new();
let path = Path::new(&self.directory)
.join("_manifests/tags")
.join(tag_name)
.join("current/link");
let mut f = File::open(path)?;
f.read_to_string(&mut buffer)?;
buffer = Tag::clean_tag(&buffer);
Ok(buffer)
}
}
/* -------------------------------------------------------------
Tag
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/// Represents a repository tag
#[serde(rename_all = "camelCase")]
#[derive(Serialize, Deserialize, Clone)]
pub struct Tag {
pub name: String,
pub hash: String,
}
impl Tag {
pub fn clean_tag (tag: &str) -> String {
let fragments: Vec<&str> = tag.split(":").collect();
if fragments.len() == 1 {
String::from(tag)
} else {
String::from(fragments[1])
}
}
}
/* -------------------------------------------------------------
File system helper functions
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
fn count_subdirectories (dir: &Path) -> IOResult<usize> {
let count = read_dir(dir)?
.filter(|entry| is_entry_sub_directory(entry))
.count();
Ok(count)
}
fn is_entry_sub_directory(entry: &IOResult<DirEntry>) -> bool {
match entry {
Ok(e) => e.path().is_dir(),
Err(_) => false,
}
}
fn get_entry_name(entry: &IOResult<DirEntry>) -> String {
match entry {
Ok(e) => match e.file_name().into_string() {
Ok(name) => String::from(name),
Err(_) => String::new(),
}
Err(_) => String::new(),
}
}
fn get_subdirectories_names (dir: &Path) -> Vec<String> {
match std::fs::read_dir(dir) {
Ok(iterator) => {
iterator
.filter(|entry| is_entry_sub_directory(entry))
.map(|entry| get_entry_name(&entry))
.filter(|name| name != "")
.collect::<Vec<_>>()
},
Err(_) => {
error!("Can't get subdirectories of {:?}", dir);
Vec::new()
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Nov 24, 21:56 (11 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2256339
Default Alt Text
(6 KB)
Attached To
Mode
rAPIREG Nasqueron private Docker registry API
Attached
Detach File
Event Timeline
Log In to Comment