1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
extern crate cargo;
extern crate walkdir;
macro_rules! bail {
($($fmt:tt)*) => (
return Err(human(&format_args!($($fmt)*)))
)
}
pub mod ops {
use std::path::{Path, PathBuf};
use std::fs;
use std::env;
use cargo::util::{CargoResult, Config, human};
use cargo::util::to_semver::ToSemver;
use cargo::core::package_id::PackageId;
use cargo::core::source::{Source, SourceId};
use cargo::core::registry::Registry;
use cargo::core::dependency::Dependency;
use cargo::sources::RegistrySource;
use walkdir::WalkDir;
pub fn clone(krate: Option<&str>,
srcid: &SourceId,
prefix: Option<&str>,
vers: Option<&str>,
config: Config)
-> CargoResult<()> {
let krate = match krate {
Some(ref k) => k,
None => bail!("specify which package to clone!"),
};
let mut src = if srcid.is_registry() {
RegistrySource::remote(&srcid, &config)
}
else if srcid.is_path(){
unimplemented!();
}
else {
unimplemented!();
};
try!(src.update());
let vers = match vers {
Some(v) => {
match v.to_semver() {
Ok(v) => v,
Err(e) => bail!("{}", e),
}
},
None => {
let dep = try!(Dependency::parse_no_deprecated(
krate, vers.as_ref().map(|s| &s[..]), &srcid));
let summaries = try!(src.query(&dep));
let latest = summaries.iter().max_by_key(|s| s.version());
match latest {
Some(l) => l.version().to_semver().unwrap(),
None => bail!("package '{}' not found", krate),
}
},
};
let pkgid = try!(PackageId::new(&krate, vers, srcid));
let krate = try!(src.download(&pkgid.clone()));
let mut dest_path = match prefix {
Some(path) => PathBuf::from(path),
None => try!(env::current_dir())
};
dest_path.push(krate.name());
try!(clone_directory(&krate.root(), &dest_path));
Ok(())
}
fn clone_directory(from: &Path, to: &Path) -> CargoResult<()> {
for entry in WalkDir::new(from) {
let entry = entry.unwrap();
let file_type = entry.file_type();
let mut to = to.to_owned();
to.push(entry.path().strip_prefix(from).unwrap());
if file_type.is_file() && entry.file_name() != ".cargo-ok" {
try!(fs::copy(&entry.path(), &to));
}
else if file_type.is_dir() {
try!(fs::create_dir(&to));
}
}
Ok(())
}
}