用dulwich程序化地执行`git checkout .`
有了这段代码
from dulwich.objects import Blob, Tree, Commit, parse_timezone
from dulwich.repo import Repo
from time import time
repo = Repo.init("myrepo", mkdir=True)
blob = Blob.from_string("my file content\n")
tree = Tree()
tree.add("spam", 0100644, blob.id)
commit = Commit()
commit.tree = tree.id
author = "Flav <foo@bar.com>"
commit.author = commit.committer = author
commit.commit_time = commit.author_time = int(time())
tz = parse_timezone('+0200')[0]
commit.commit_timezone = commit.author_timezone = tz
commit.encoding = "UTF-8"
commit.message = "initial commit"
o_sto = repo.object_store
o_sto.add_object(blob)
o_sto.add_object(tree)
o_sto.add_object(commit)
repo.refs["HEAD"] = commit.id
我发现提交记录里有这个提交,但是新创建的文件还在等待删除状态(git status
这么说的)。
用 git checkout .
可以解决这个问题。
我的问题是:怎么用 dulwich 这个库来程序化地执行 git checkout .
呢?
4 个回答
1
如果你想从远程仓库查看一个已经存在的分支,下面是我最终是怎么做到的:
from dulwich import porcelain
gitlab_server_address = 'gitlab.example.com/foo/my_remote_repo.git'
username = 'foo@bar.com'
password = 'mocraboof'
repo = porcelain.clone(gitlab_server_address, target='myrepo', username=username, password=password)
# or if repo already exists:
# repo = porcelain.open_repo('gholam')
branch_name = 'thebranch'
porcelain.branch_create(repo, branch_name)
porcelain.update_head(repo, target=branch_name, detached=False, new_branch=None)
porcelain.pull(repo, gitlab_server_address, refspecs=f'refs/heads/{branch_name}', username=username, password=password)
问题在于,当你用dulwich克隆一个仓库时,它只会获取主分支(main/master),我找不到其他方法来获取其他分支。所以我先从主分支创建一个新的分支,然后再从远程拉取。
(如果你的主分支在远程分支的初始提交之前,这种方法可能不奏效。)
9
Git的状态显示文件被删除了,因为在工作副本中找不到这个文件,所以重新检出(checkout)文件就能修复这个状态。
看起来在dulwich中还没有支持高级工作副本的类和函数。你需要直接处理树(trees)、数据块(blobs)和解包对象。
好的,我接受了这个挑战:我可以用Dulwich做一个基本的检出操作:
#get repository object of current directory
repo = Repo('.')
#get tree corresponding to the head commit
tree_id = repo["HEAD"].tree
#iterate over tree content, giving path and blob sha.
for entry in repo.object_store.iter_tree_contents(tree_id):
path = entry.in_path(repo.path).path
dulwich.file.ensure_dir_exists(os.path.split(path)[0])
with open(path, 'wb') as file:
#write blob's content to file
file.write(repo[entry.sha].as_raw_string())
这个操作不会删除那些必须删除的文件,也不会关心你的索引等等。
你可以查看 Mark Mikofski的GitHub项目,里面有基于这个的更完整的代码。
3
从0.8.4版本开始,现在可以使用一个叫做dulwich.index.build_index_from_tree()
的方法。
这个方法可以把一个树结构写入到索引文件和文件系统(也就是你的工作副本)中,这其实就是一种非常基础的检出操作。
请注意:
现有的索引会被清空,内容不会和工作目录中的内容合并。这个方法只适合全新克隆的项目。
我用下面的代码让它工作了:
from dulwich import index, repo
#get repository object of current directory
repo = repo.Repo('.')
indexfile = repo.index_path()
#we want to checkout HEAD
tree = repo["HEAD"].tree
index.build_index_from_tree(repo.path, indexfile, repo.object_store, tree)