我正在尝试建立一个业余爱好应用程序,为Git提供一个用户界面。我正在尝试执行相当于git restore --staged <file>
的操作。在文件是新添加到索引中的情况下,下面的*似乎成功地执行了正确的操作,因此我可以只从索引中删除它,但我不确定如何处理文件以前已添加到索引中并已被修改的情况。我对Git和C的理解都很有限,这使得我很难自己解决这个问题。
use git2;
fn main() {
let repo = git2::Repository::open("myrepo").unwrap();
let mut index = repo.index().unwrap();
let statuses = repo.statuses(None).unwrap();
let file_status_entry = statuses.get(0).unwrap();
let ct_path = std::path::Path::new(file_status_entry.path().unwrap());
let file_status = file_status_entry.status();
if file_status.is_index_new() {
index.remove(ct_path, 0).unwrap();
} else {
// not sure what to do here
index.remove(ct_path, 0).unwrap();
}
index.write().unwrap();
}
1条答案
按热度按时间jobtbby31#
git restore
命令是...很复杂。因此,无论您使用什么语言和库,准确地模拟它也是很复杂的。但是,如果您将自己限制为git restore
的行为的一个示例(例如,git restore --staged
),那么事情就简单了。我不熟悉这里的Rust库版本,所以我只能告诉您CGIT如何处理
git restore --staged *path*
。该操作“目标”是将某个路径从某个源提交复制到Git的索引中。使用--staged
时,源提交默认为HEAD
(除非用--source
覆盖)。此操作不会影响工作树(当然,除非您还添加了--worktree
)。铁 rust 当量将相当于:
在这一点上,您已经准备好接受逻辑。注意:对于
git restore
,参数不是路径名,而是路径规范,这需要在各种情况下迭代所有匹配的路径名(例如,git restore --staged "*"
)。这可能会影响下面的逻辑(如果您正在git restore
-ing*/foo
,并且有六个目录可能具有foo
,但其中只有四个目录确实具有foo
,则其他两个目录应该不会出现“不匹配”的情况)。如果您只处理单个路径名称,则您的工作将得到简化,如下所示。如果命名文件存在于当前提交中,请将其数据复制到该路径下的索引中,删除所有未合并的索引项(非零分段项),然后继续执行“重写索引”步骤。
否则(命名文件*不存在于本次提交中):
如果指定的文件存在于索引中,请删除所有这些条目并继续执行重写索引步骤。
否则,错误-退出,并出现样式不匹配错误(
error: pathspec 'foo' did not match any file(s) know to git
)。一旦您对单个文件(没有路径规范,只列出了一个文件)或所有适当的文件(GLOBING或其他文件)执行了此操作,如果您已经更新了索引,现在就可以将其放回原处了。这包括将新的内容索引写入在第二个初始步骤中作为锁获得的
index.lock
文件,将其刷新到磁盘(如果操作系统具有fsync
,请确保将其fsync
),并对其进行重命名以释放锁并将其放在适当的位置作为索引。还要记住,要处理任何
git worktree add
复杂情况(这些情况会导致不同的默认索引文件)和/或GIT_INDEX_FILE
环境复杂情况。图书馆可能会(也可能不会)涵盖这些内容。