A API de criação de árvore do Github nos permite passar sha = null
para indicar que o blob especificado precisa ser excluído.
No entanto, não tenho como passar essa informação para meu InputGitTreeElement
. Posso dar um str ou um github.GithubObject.NotSet
. Isso significa que não tenho como excluir arquivos de uma árvore usando o PyGithub (gostaria de excluir vários arquivos em um único commit, portanto, a criação de uma árvore é a escolha ideal para mim).
O design atual é apenas para passar sha
se ele estiver realmente definido:
https://github.com/PyGithub/PyGithub/blob/540a085001/github/InputGitTreeElement.py#L81
Eu posso entender que passar None
vai contra o design. Acho que algo como github.GithubObject.Null
poderia ser introduzido para dizer explicitamente que este campo é null
. Ele pode ser usado em qualquer lugar em que a API GH aceite um valor nulo.
Exemplo
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
)
Isso excluirá my/dir/my_file.txt
Minha solução alternativa atual é atingir diretamente a API para criar a árvore (usando solicitações, definindo sha=None
), obter a árvore de sha e usá-la com o pygithub para meu fluxo de trabalho restante (confirmação, etc).
Por favor, me informe caso eu tenha entendido mal algum aspecto ou se algo precisar ser elaborado.
Na verdade, NotSet é uma classe em seu próprio direito que não tem nada a ver com Nenhum, então se você passar em Nenhum, deve funcionar bem.
Oh, espere, entendo. Afirmamos que é um str! Certo, ok, então eu acho que afrouxar para permitir Nenhum está perfeitamente bem então, boa pegada.
Estou tendo muitos problemas com essa mudança. Fiz as alterações necessárias, mas a API create_git_tree () retorna 422 GitRPC :: BadObjectState ou um erro 404 não encontrado genérico. Você é capaz de fornecer um exemplo funcional em um repo público para que eu possa obter os dados de replay para o teste de unidade?
Meu código é para um repositório privado, então acabei de criar uma versão simplificada dele para você aqui:
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)
Um motivo pelo qual também recebi 422 GitRPC::BadObjectState
foi porque estava fornecendo nomes de arquivos em paths
que não existiam na árvore base. Por exemplo, tente corromper 1 dos nomes de arquivo acima.
Não posso tornar meu repo de teste público, mas aqui está a estrutura, basta configurar os arquivos fictícios em seu próprio repo
pods/
raghav/
network/
resources.tf
Muito obrigado! Vou tentar fazer isso no dia seguinte ou depois. Talvez sem os f-strings. :-)
@stevenk wohoo! obrigado por consertar isso
cc @rohitpaulk
@stevenk Estou criando um commit como este, mas ele confirma mesmo se o diff do arquivo for zero. Por favor, qualquer ajuda sobre como se comprometer somente se houver alguma diferença. Obrigado !
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 Os SHAs de árvore são essencialmente somas de verificação de todos os arquivos em seu repositório, então você pode apenas verificar se eles correspondem.
Em seu contexto, seria algo como:
if tree.sha != base_tree.sha:
# then commit
(Não me lembro do método exato usado para buscar um sha, mas você entendeu)
Comentários muito úteis
Muito obrigado! Vou tentar fazer isso no dia seguinte ou depois. Talvez sem os f-strings. :-)