Pygithub: InputGitTreeElement deve permitir a passagem de "null" para sha

Criado em 14 dez. 2019  ·  8Comentários  ·  Fonte: PyGithub/PyGithub

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.

Comentários muito úteis

Muito obrigado! Vou tentar fazer isso no dia seguinte ou depois. Talvez sem os f-strings. :-)

Todos 8 comentários

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)

Esta página foi útil?
0 / 5 - 0 avaliações