Home > front end >  Rust libgit2: how to add --force
Rust libgit2: how to add --force

Time:07-09

How to do a git add --force * with libgit2 in Rust?

I tried the following code from the documentation:

use git2::{Index, IndexAddOption, Repository};

let repo = Repository::open("/path/to/a/repo").expect("failed to open");
let mut index = repo.index().expect("cannot get the Index file");
index.add_all(["*"].iter(), IndexAddOption::DEFAULT, None);
index.write();

and it seems to work. Then I replaced IndexAddOption::DEFAULT to IndexAddOption::FORCE and I get the following error (example from a test on the Linux Kernel source code):

Error { code: -1, klass: 10, message: "invalid path: 'arch/i386/'" }', src/main.rs:58:14

What I understand is that when I use FORCE, it will add "files" that are "non-standard" (like binaries or even directories) for git. That's why it is trying to add a directory and raises the invalid path error.

I just would like to implement a git add --force * using libgit2 API in Rust. Any suggestions?

Thank you.

CodePudding user response:

It is possible to define a callback function IndexMatchedPath like in this example.

Using this function raises the same error with a precision that it is from git.status_file(). In fact, on Line 42 of the previous example, we have this line:

        let status = repo.status_file(path).unwrap();

First, to remove the error, we can check if path is a directory or not. We can ignore if it is a directory like mentioned in the documentation of git2::IndexMatchedPath:

Return 0 to confirm the operation on the item, > 0 to skip the item, and < 0 to abort the scan.

However, we still have the error with if path.is_dir() { 1 }else {...}. Hence, just extracting the string with path.to_str().unwrap() and testing if it ends_with("/") seems to work. Our function looks like this:

        let cb = &mut |path: &Path, _matched_spec: &[u8]| -> i32 {
            if path.to_str().unwrap().ends_with("/") { 1 }else{
                let status = self.repository.status_file(path).unwrap();
                ...
        };

Now that we removed the error, we move to the implementation of --force. In the example, it checks the status of the files to add:

        let ret = if status.contains(git2::Status::WT_MODIFIED)
            || status.contains(git2::Status::WT_NEW)

It adds modified or new files (more info here). So, in addition of modified and new files, we can include ignored files with git2::Status::IGNORED:

        let ret = if status.contains(git2::Status::WT_MODIFIED)
            || status.contains(git2::Status::WT_NEW)
            || status.contains(git2::Status::IGNORED)

So now, we use IndexAddOption::FORCE and cb:

index.add_all(["*"].iter(), IndexAddOption::FORCE, Some(cb as &mut git2::IndexMatchedPath));
  • Related