Github的Tree创建api允许我们通过sha = null
来表示需要删除指定的blob。
但是,我无法将此信息传递给我的InputGitTreeElement
。 我可以给它一个 str 或一个github.GithubObject.NotSet
。 这意味着我无法使用 PyGithub 从树中删除文件(我想在一次提交中删除多个文件,因此创建树是我的理想选择)。
当前的设计是只有在实际设置时才传递sha
:
https://github.com/PyGithub/PyGithub/blob/540a085001/github/InputGitTreeElement.py#L81
我可以理解传递None
与设计背道而驰。 我认为可以引入类似github.GithubObject.Null
来明确表示该字段是null
。 它可以在 GH API 接受空值的任何地方使用。
例子
new_tree = repo.create_git_tree(
[
InputGitTreeElement(
path="my/dir/my_file.txt", mode="100644", type="blob", sha=github.GithubObject.Null
),
],
base_tree=head_commit.tree
)
这将删除my/dir/my_file.txt
我目前的解决方法是直接点击 api 来创建树(使用请求,设置sha=None
),获取树 sha 并将它与 pygithub 一起用于我剩余的工作流程(提交等)。
如果我误解了某些方面或需要详细说明,请告诉我。
实际上 NotSet 本身就是一个与 None 无关的类,所以如果你传入 None,它应该可以正常工作。
哦,等等,我明白了。 我们断言它是一个 str! 是的,好的,所以我认为放松以允许 None 是完全没问题的,很好的捕获。
我对这个变化有很多麻烦。 我已经进行了必要的更改,但是 create_git_tree() API 要么返回 422 GitRPC::BadObjectState 要么返回通用的 404 Not Found 错误。 您能否针对公共存储库提供一个工作示例,以便我可以获取单元测试的重放数据?
我的代码是用于私人仓库的,所以我在这里为您创建了一个精简版本:
import json
import requests
from http import HTTPStatus
from github import Github
TOKEN = "<GITHUB TOKEN>"
gh_client = Github(TOKEN)
repo = gh_client.get_repo("duaraghav8/test")
my_branch = "tree-test"
# paths is list of files to delete
paths = ["pods/raghav/network/resources.tf", "abc"]
sha = repo.get_branch(my_branch).commit.sha
head_commit = repo.get_git_commit(sha)
tree_objects = [
{"path": path, "mode": "100644", "type": "blob", "sha": None}
for path in paths
]
payload = {
"base_tree": head_commit.tree.sha,
"tree": tree_objects,
}
headers = {"Authorization": f"token {TOKEN}"}
url = f"{repo.url}/git/trees"
response = requests.post(url, headers=headers, data=json.dumps(payload))
if response.status_code != HTTPStatus.CREATED:
raise RuntimeError("Failed")
new_tree_sha = response.json()["sha"]
tree = repo.get_git_tree(new_tree_sha)
我也收到422 GitRPC::BadObjectState
原因是因为我在paths
中提供了基本树中不存在的文件名。 例如,尝试破坏上述文件名中的 1 个。
我无法公开我的测试存储库,但这是结构,只需在您自己的存储库中设置虚拟文件
pods/
raghav/
network/
resources.tf
非常感谢! 我会在第二天左右尝试一下。 也许没有 f 弦。 :-)
@stevenk 哇哦! 感谢您解决这个问题
抄送@rohitpaulk
@stevenk 我正在创建这样的提交,但即使文件差异为零,也会提交。 请提供有关如何提交的任何帮助,仅当有一些 diff 时。 谢谢 !
file_list = [a.txt]
file_names =[a.txt]
for i, entry in enumerate(file_list):
with open(entry) as input_file:
data = input_file.read()
element = InputGitTreeElement(file_names[i], '100644', 'blob', data)
element_list.append(element)
tree = repo.create_git_tree(element_list, base_tree)
parent = repo.get_git_commit(master_sha)
commit = repo.create_git_commit(commit_message, tree, [parent])
@Abhishek627树 SHA 本质上是存储库中所有文件的校验和,因此您可以检查它们是否匹配。
在您的上下文中,这将类似于:
if tree.sha != base_tree.sha:
# then commit
(我不记得用于获取 sha 的确切方法,但您明白了)
最有用的评论
非常感谢! 我会在第二天左右尝试一下。 也许没有 f 弦。 :-)