Skip to content

Commit

Permalink
Initial work on 'commit' command
Browse files Browse the repository at this point in the history
  • Loading branch information
sdleffler committed Oct 17, 2017
1 parent 2b9f683 commit 8a11ce2
Show file tree
Hide file tree
Showing 13 changed files with 363 additions and 224 deletions.
85 changes: 85 additions & 0 deletions src/bin/commit.rs
@@ -0,0 +1,85 @@
use chrono::prelude::*;
use clap::{App, SubCommand, Arg, ArgMatches};
use futures::prelude::*;
use globset::{Glob, GlobSetBuilder};

use attaca::Repository;
use attaca::repository::Head;

use errors::*;
use trace::Progress;


pub fn command() -> App<'static, 'static> {
SubCommand::with_name("commit")
.help("Commit a change to the local repository.")
.arg(
Arg::with_name("INCLUDE")
.short("i")
.long("inc")
.takes_value(true)
.multiple(true)
.help(
"Zero or more patterns matching files to include in the commit.",
),
)
.arg(
Arg::with_name("EXCLUDE")
.short("e")
.long("exc")
.takes_value(true)
.multiple(true)
.help(
"Zero or more patterns matching files to exclude from the commit.",
),
)
.arg(Arg::with_name("MESSAGE").index(1).required(true).help(
"The commit message.",
))
}


pub fn go(repository: &mut Repository, matches: &ArgMatches) -> Result<()> {
let include = if let Some(paths) = matches.values_of("INCLUDE") {
let mut builder = GlobSetBuilder::new();
for path in paths {
builder.add(Glob::new(path)?);
}
Some(builder.build()?)
} else {
None
};

let exclude = if let Some(paths) = matches.values_of("EXCLUDE") {
let mut builder = GlobSetBuilder::new();
for path in paths {
builder.add(Glob::new(path)?);
}
Some(builder.build()?)
} else {
None
};

let message = matches.value_of("MESSAGE").unwrap().to_owned();

repository.index.update()?;

let commit_hash = {
let mut ctx = repository.local(Progress::new(None))?;
let head = ctx.refs.head_hash().cloned().into_iter().collect();
ctx.hash_commit(
include.as_ref(),
exclude.as_ref(),
head,
message,
Utc::now(),
).wait()?
};

repository.refs.head = Head::Detached(commit_hash);
repository.index.iter_mut().for_each(
|(_, entry)| entry.added = false,
);

Ok(())
}
7 changes: 7 additions & 0 deletions src/bin/main.rs
@@ -1,4 +1,5 @@
extern crate attaca;
extern crate chrono;
#[macro_use]
extern crate clap;
#[macro_use]
Expand All @@ -12,11 +13,13 @@ extern crate itertools;
extern crate memmap;

mod catalog;
mod commit;
mod errors;
mod index;
mod init;
mod remote;
mod stats;
mod status;
mod test;
mod trace;
mod track;
Expand All @@ -42,10 +45,12 @@ fn command() -> App<'static, 'static> {
.about(crate_description!())
.version(crate_version!())
.subcommand(catalog::command())
.subcommand(commit::command())
.subcommand(index::command())
.subcommand(init::command())
.subcommand(remote::command())
.subcommand(stats::command())
.subcommand(status::command())
.subcommand(utils::command())
.subcommand(test::command())
.subcommand(track::command())
Expand All @@ -64,9 +69,11 @@ fn go(matches: &ArgMatches) -> Result<()> {

let result = match other {
("catalog", Some(sub_m)) => catalog::go(&mut repository, sub_m),
("commit", Some(sub_m)) => commit::go(&mut repository, sub_m),
("index", Some(sub_m)) => index::go(&mut repository, sub_m),
("remote", Some(sub_m)) => remote::go(&mut repository, sub_m),
("stats", Some(sub_m)) => stats::go(&mut repository, sub_m),
("status", Some(sub_m)) => status::go(&mut repository, sub_m),
("test", Some(sub_m)) => test::go(&mut repository, sub_m),
("untrack", Some(sub_m)) => untrack::go(&mut repository, sub_m),
("utils", Some(sub_m)) => utils::go(&mut repository, sub_m),
Expand Down
66 changes: 66 additions & 0 deletions src/bin/status.rs
@@ -0,0 +1,66 @@
use clap::{App, SubCommand, ArgMatches};

use attaca::Repository;
use attaca::index::Cached;
use errors::*;


pub fn command() -> App<'static, 'static> {
SubCommand::with_name("status").about("Show repository status, including tracked/added files.")
}


pub fn go(repository: &mut Repository, _matches: &ArgMatches) -> Result<()> {
repository.index.update()?;

let catalog = repository.catalogs.get(None)?;
println!("{} local objects.", catalog.len());

let mut added = Vec::new();
let mut tracked = Vec::new();

for (path, entry) in repository.index.iter() {
if entry.tracked {
tracked.push((path, entry));
} else if entry.added {
added.push((path, entry));
}
}

println!("Tracked:");

for (path, entry) in tracked {
match entry.cached {
Cached::Hashed(hashed) => {
println!(
"\t[{:?}] {} Hashed({})",
entry.hygiene,
path.display(),
&hashed.to_string()[..6]
)
}
Cached::Unhashed => println!("\t[{:?}] {} Unhashed", entry.hygiene, path.display()),
Cached::Removed => println!("\t[{:?}] {} Removed", entry.hygiene, path.display()),
}
}

println!("Added:");

for (path, entry) in added {
match entry.cached {
Cached::Hashed(hashed) => {
println!(
"\t[{:?}] {} Hashed({})",
entry.hygiene,
path.display(),
&hashed.to_string()[..6]
)
}
Cached::Unhashed => println!("\t[{:?}] {} Unhashed", entry.hygiene, path.display()),
Cached::Removed => println!("\t[{:?}] {} Removed", entry.hygiene, path.display()),
}
}


Ok(())
}
2 changes: 1 addition & 1 deletion src/bin/test/chunk.rs
Expand Up @@ -57,7 +57,7 @@ impl Trace for TraceSplit {

pub fn go(repository: &mut Repository, matches: &ArgMatches) -> Result<()> {
let trace = TraceSplit::default();
let mut ctx = repository.local(trace.clone())?;
let ctx = repository.local(trace.clone())?;

ctx.split_file(matches.value_of("INPUT").unwrap())
.for_each(|_| Ok(()))
Expand Down
2 changes: 1 addition & 1 deletion src/bin/test/marshal/file.rs
Expand Up @@ -44,7 +44,7 @@ fn marshal<T: Trace, P: AsRef<Path>>(
trace: T,
path: P,
) -> Result<ObjectHash> {
let mut context = repository.local(trace)?;
let context = repository.local(trace)?;
let chunk_stream = context.split_file(path);
let hash_future = context.hash_file(chunk_stream);
let write_future = context.close();
Expand Down
12 changes: 7 additions & 5 deletions src/bin/test/marshal/subtree.rs
Expand Up @@ -45,15 +45,15 @@ fn marshal<T: Trace, P: AsRef<Path>>(
trace: T,
path: P,
) -> Result<ObjectHash> {
let mut context = repository.local(trace)?;
let context = repository.local(trace)?;

let mut entries = FuturesUnordered::new();
let mut stack = Vec::new();

let absolute_path = if path.as_ref().is_absolute() {
path.as_ref().to_owned()
} else {
repository.paths.base.join(path.as_ref())
context.paths.base.join(path.as_ref())
};

stack.push(absolute_path.read_dir()?);
Expand All @@ -62,15 +62,17 @@ fn marshal<T: Trace, P: AsRef<Path>>(
for dir_entry_res in iter {
let dir_entry = dir_entry_res?;
let absolute_path = dir_entry.path();
let relative_path = absolute_path.strip_prefix(&repository.paths.base).unwrap();

if absolute_path.symlink_metadata()?.is_dir() {
stack.push(absolute_path.read_dir()?);
} else {
let chunk_stream = context.split_file(&absolute_path);
let entry_path = relative_path.to_owned();
let relative_path = absolute_path
.strip_prefix(&context.paths.base)
.unwrap()
.to_owned();
entries.push(context.hash_file(chunk_stream).map(
|hash| (entry_path, hash),
|hash| (relative_path, hash),
));
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/bin/test/suite/write_all.rs
Expand Up @@ -39,7 +39,7 @@ pub fn command() -> App<'static, 'static> {

fn run<T: Trace>(repository: &mut Repository, matches: &ArgMatches, trace: T) -> Result<()> {
let path = matches.value_of("INPUT").unwrap();
let mut context = repository.remote("_debug", trace)?;
let context = repository.remote("_debug", trace)?;

let chunk_stream = context.split_file(path);
let hash_future = context.hash_file(chunk_stream);
Expand Down
15 changes: 9 additions & 6 deletions src/bin/track.rs
Expand Up @@ -8,15 +8,13 @@ use errors::*;

pub fn command() -> App<'static, 'static> {
SubCommand::with_name("track")
.arg(Arg::with_name("PATH")
.help("Begin tracking changes to files.")
.index(1)
.multiple(true))
.help("Begin tracking changes to files.")
.arg(Arg::with_name("PATH").index(1).multiple(true))
}


pub fn go(repository: &mut Repository, matches: &ArgMatches) -> Result<()> {
let glob_set = if let Some(paths) = matches.values_of("PATH") {
let pattern = if let Some(paths) = matches.values_of("PATH") {
let mut builder = GlobSetBuilder::new();
for path in paths {
builder.add(Glob::new(path)?);
Expand All @@ -26,7 +24,12 @@ pub fn go(repository: &mut Repository, matches: &ArgMatches) -> Result<()> {
bail!("No files!");
};

repository.index.track(&glob_set)?;
repository.index.register(&pattern)?;
repository
.index
.iter_mut()
.filter(|&(path, _)| pattern.is_match(path))
.for_each(|(_, entry)| entry.tracked = true);

Ok(())
}
20 changes: 13 additions & 7 deletions src/bin/untrack.rs
Expand Up @@ -7,16 +7,17 @@ use errors::*;


pub fn command() -> App<'static, 'static> {
SubCommand::with_name("untrack")
.arg(Arg::with_name("PATH")
.help("Stop tracking changes to files.")
.index(1)
.multiple(true))
SubCommand::with_name("untrack").arg(
Arg::with_name("PATH")
.help("Stop tracking changes to files.")
.index(1)
.multiple(true),
)
}


pub fn go(repository: &mut Repository, matches: &ArgMatches) -> Result<()> {
let glob_set = if let Some(paths) = matches.values_of("PATH") {
let pattern = if let Some(paths) = matches.values_of("PATH") {
let mut builder = GlobSetBuilder::new();
for path in paths {
builder.add(Glob::new(path)?);
Expand All @@ -26,7 +27,12 @@ pub fn go(repository: &mut Repository, matches: &ArgMatches) -> Result<()> {
bail!("No files!");
};

repository.index.untrack(&glob_set);
repository.index.register(&pattern)?;
repository
.index
.iter_mut()
.filter(|&(path, _)| pattern.is_match(path))
.for_each(|(_, entry)| entry.tracked = false);

Ok(())
}

0 comments on commit 8a11ce2

Please sign in to comment.