Adding an untracked change iterator

pmeunier
Jul 11, 2021, 9:03 PM
HSEYMLO2DJCDGBO4F7T6NFMFSZ4TMSOBH5XGIU5NYOEFKUSV5UKAC

Dependencies

  • [2] VSTBTRYE Fixing a compilation error
  • [3] FXEDPLRI Resurrecting tests, and type cleanup (no need for Arc<RwLock<…>> anymore)
  • [4] VIHXB7SG commands: set up pager for diff, change, and credit
  • [5] 4OCC6D42 Recursive add
  • [6] ZRUPLBBT Colours in diff and change: separating concerns and dependencies
  • [7] 5OGOE4VW Store the current channel in the pristine
  • [8] 2K7JLB4Z No pager on Windows
  • [9] R3H7D42U Debugging `pijul git`: proper error reporting
  • [10] OJZWJUF2 MUCH faster `pijul add -r`
  • [11] CCLLB7OI Upgrading to Sanakirja 0.15 + version bump
  • [12] G7VOM2IM Returning an error when recording non-existent paths
  • [13] CCFJ7VO3 Renaming "Record" to "Hunk" in the changes
  • [14] V435QOJR Using path-slash to fix path issues on Windows
  • [15] 5BB266P6 Optional colours in the global config file
  • [16] ZHABNS3S Canonicalize all paths
  • [17] L4JXJHWX pijul/*: reorganize imports and remove extern crate
  • [18] 2RXOCWUW Making libpijul deterministic (and getting rid of `rand`)
  • [19] YDKNUL6B Add `diff --short` that lists changes without showing them
  • [20] SXEYMYF7 Fixing the bad changes in history (unfortunately, by rebooting).
  • [21] 3J6IK4W2 Explicitly adding .pijul is now forbidden
  • [22] 4VWXL6KQ Correct handling of ignore files
  • [23] I24UEJQL Various post-fire fixes
  • [24] VYHHOEYH Versions and formatting
  • [25] BZSC7VMY address clippy lints
  • [26] I52XSRUH Massive cleanup, and simplification
  • [*] KWAMD2KR A few fixes in the documentation comments
  • [*] VO5OQW4W Removing anyhow in libpijul

Change contents

  • replacement in pijul/src/commands/file_operations.rs at line 144
    [4.137][4.137:170]()
    txn.clone(),
    [4.137]
    [4.170]
    &txn,
  • replacement in pijul/src/commands/diff.rs at line 8
    [4.2595][4.3029:3060]()
    use libpijul::{MutTxnT, TxnT};
    [4.2595]
    [4.2654]
    use libpijul::{MutTxnT, TxnT, TxnTExt};
  • edit in pijul/src/commands/diff.rs at line 30
    [4.49]
    [28.3165]
    /// Include the untracked files
    #[clap(long = "untracked")]
    pub untracked: bool,
  • replacement in pijul/src/commands/diff.rs at line 112
    [4.175800][4.175800:175893](),[4.175893][4.628:817](),[4.817][4.0:824](),[4.824][4.1663:1755](),[4.1663][4.1663:1755]()
    let mut changes = BTreeMap::new();
    for ch in change.changes.iter() {
    changes
    .entry(ch.path())
    .or_insert_with(Vec::new)
    .push(Status {
    operation: match ch {
    Hunk::FileMove { .. } => "file move",
    Hunk::FileDel { .. } => "file del",
    Hunk::FileUndel { .. } => "file undel",
    Hunk::SolveNameConflict { .. } => "solve name conflict",
    Hunk::UnsolveNameConflict { .. } => "unsolve name conflict",
    Hunk::FileAdd { .. } => "file add",
    Hunk::Edit { .. } => "edit",
    Hunk::Replacement { .. } => "replacement",
    Hunk::SolveOrderConflict { .. } => "solve order conflict",
    Hunk::UnsolveOrderConflict { .. } => "unsolve order conflict",
    Hunk::ResurrectZombies { .. } => "resurrect zombies",
    },
    line: ch.line(),
    });
    [4.175800]
    [4.176894]
    if self.untracked {
    serde_json::to_writer_pretty(
    &mut std::io::stdout(),
    &untracked(&repo, &*txn)?.collect::<Vec<_>>(),
    )?;
    writeln!(stdout)?;
    } else {
    let mut changes = BTreeMap::new();
    for ch in change.changes.iter() {
    changes
    .entry(ch.path())
    .or_insert_with(Vec::new)
    .push(Status {
    operation: match ch {
    Hunk::FileMove { .. } => "file move",
    Hunk::FileDel { .. } => "file del",
    Hunk::FileUndel { .. } => "file undel",
    Hunk::SolveNameConflict { .. } => "solve name conflict",
    Hunk::UnsolveNameConflict { .. } => "unsolve name conflict",
    Hunk::FileAdd { .. } => "file add",
    Hunk::Edit { .. } => "edit",
    Hunk::Replacement { .. } => "replacement",
    Hunk::SolveOrderConflict { .. } => "solve order conflict",
    Hunk::UnsolveOrderConflict { .. } => "unsolve order conflict",
    Hunk::ResurrectZombies { .. } => "resurrect zombies",
    },
    line: ch.line(),
    });
    }
    serde_json::to_writer_pretty(&mut std::io::stdout(), &changes)?;
    writeln!(stdout)?;
  • edit in pijul/src/commands/diff.rs at line 144
    [4.176908][4.176908:176985](),[4.176985][4.1756:1787]()
    serde_json::to_writer_pretty(&mut std::io::stdout(), &changes)?;
    writeln!(stdout)?;
  • edit in pijul/src/commands/diff.rs at line 180
    [2.45]
    [4.5627]
    }
    for path in untracked(&repo, &*txn)? {
    writeln!(stdout, "U {}", path.to_str().unwrap())?;
  • edit in pijul/src/commands/diff.rs at line 184
    [4.5641]
    [4.177020]
    } else if self.untracked {
    for path in untracked(&repo, &*txn)? {
    writeln!(stdout, "{}", path.to_str().unwrap())?;
    }
  • edit in pijul/src/commands/diff.rs at line 306
    [4.951]
    [4.177744]
    }
    fn untracked<'a, T: TxnTExt>(
    repo: &Repository,
    txn: &'a T,
    ) -> Result<impl Iterator<Item = PathBuf> + 'a, anyhow::Error> {
    let repo_path = CanonicalPathBuf::canonicalize(&repo.path)?;
    let threads = num_cpus::get();
    Ok(repo
    .working_copy
    .iterate_prefix_rec(repo_path.clone(), repo_path.clone(), threads)?
    .filter_map(move |x| {
    let (path, _) = x.unwrap();
    let path_ = if let Ok(path) = path.as_path().strip_prefix(&repo_path.as_path()) {
    path
    } else {
    return None;
    };
    use path_slash::PathExt;
    let path_str = path_.to_slash_lossy();
    if !txn.is_tracked(&path_str).unwrap() {
    Some(path)
    } else {
    None
    }
    }))
  • edit in libpijul/src/working_copy/filesystem.rs at line 87
    [29.3771]
    [29.3771]
    #[error(transparent)]
    Txn(#[from] T),
    }
    pub struct Untracked {
    join: Option<std::thread::JoinHandle<Result<(), std::io::Error>>>,
    receiver: std::sync::mpsc::Receiver<(PathBuf, bool)>,
    }
    impl Iterator for Untracked {
    type Item = Result<(PathBuf, bool), std::io::Error>;
    fn next(&mut self) -> Option<Self::Item> {
    if let Ok(x) = self.receiver.recv() {
    return Some(Ok(x));
    } else if let Some(j) = self.join.take() {
    if let Ok(Err(e)) = j.join() {
    return Some(Err(e));
    }
    }
    None
    }
  • replacement in libpijul/src/working_copy/filesystem.rs at line 164
    [4.1702][3.758:782]()
    txn: ArcTxn<T>,
    [4.1702]
    [4.1756]
    txn: &ArcTxn<T>,
  • edit in libpijul/src/working_copy/filesystem.rs at line 170
    [4.19679]
    [4.1935]
    let mut txn = txn.write();
    for p in self.iterate_prefix_rec(repo_path.clone(), full.clone(), threads)? {
    let (path, is_dir) = p?;
    info!("Adding {:?}", path);
    use path_slash::PathExt;
    let path_str = path.to_slash_lossy();
    match txn.add(&path_str, is_dir, salt) {
    Ok(()) => {}
    Err(crate::fs::FsError::AlreadyInRepo(_)) => {}
    Err(e) => return Err(e.into()),
    }
    }
    Ok(())
    }
    pub fn iterate_prefix_rec(
    &self,
    repo_path: CanonicalPathBuf,
    full: CanonicalPathBuf,
    threads: usize,
    ) -> Result<Untracked, std::io::Error> {
  • replacement in libpijul/src/working_copy/filesystem.rs at line 202
    [4.268][4.268:295]()
    return Ok(());
    [4.268]
    [4.175]
    return Ok(Untracked {
    join: None,
    receiver,
    });
  • replacement in libpijul/src/working_copy/filesystem.rs at line 207
    [4.185][4.19680:19764](),[4.1902][4.19680:19764]()
    let t = std::thread::spawn(move || -> Result<(), AddError<T::GraphError>> {
    [4.185]
    [4.186]
    let t = std::thread::spawn(move || -> Result<(), std::io::Error> {
  • replacement in libpijul/src/working_copy/filesystem.rs at line 254
    [4.2857][4.2857:2858](),[4.2858][3.783:818](),[3.818][4.2858:2955](),[4.28110][4.2858:2955](),[4.2858][4.2858:2955](),[4.2955][4.1036:1123](),[4.1123][4.1895:1948](),[4.1170][4.1988:2143](),[4.1948][4.1988:2143](),[4.1988][4.1988:2143](),[4.2143][4.3045:3105](),[4.3045][4.3045:3105](),[4.1570][4.210920:210945](),[4.3105][4.210920:210945](),[4.3735][4.210920:210945](),[4.210920][4.210920:210945]()
    let mut txn = txn.write();
    while let Ok((path, is_dir)) = receiver.recv() {
    info!("Adding {:?}", path);
    use path_slash::PathExt;
    let path_str = path.to_slash_lossy();
    match txn.add(&path_str, is_dir, salt) {
    Ok(()) => {}
    Err(crate::fs::FsError::AlreadyInRepo(_)) => {}
    Err(e) => return Err(e.into()),
    }
    }
    if let Ok(t) = t.join() {
    t?
    }
    Ok(())
    [4.2857]
    [4.210945]
    Ok(Untracked {
    join: Some(t),
    receiver,
    })
  • replacement in libpijul/src/working_copy/filesystem.rs at line 278
    [4.390][4.1969:2044]()
    self.add_prefix_rec(txn.clone(), repo_path, full, threads, salt)?;
    [4.390]
    [4.459]
    {
    let path = if let Ok(path) = full.as_path().strip_prefix(&repo_path.as_path()) {
    path
    } else {
    return Ok(());
    };
    use path_slash::PathExt;
    let path_str = path.to_slash_lossy();
    if !txn.read().is_tracked(&path_str)? {
    self.add_prefix_rec(&txn, repo_path, full, threads, salt)?;
    }
    }
  • file addition: .ignore (----------)
    [1.0]
    target