L' API de création d'arbre de Github nous permet de passer sha = null
pour indiquer que le blob spécifié doit être supprimé.
Cependant, je n'ai aucun moyen de transmettre cette information à mon InputGitTreeElement
. Je peux soit lui donner un str ou un github.GithubObject.NotSet
. Cela signifie que je n'ai aucun moyen de supprimer des fichiers d'un arbre à l'aide de PyGithub (j'aimerais supprimer plusieurs fichiers en un seul commit, donc la création d'arbres est le choix idéal pour moi).
La conception actuelle consiste à ne transmettre le sha
s'il est réellement défini :
https://github.com/PyGithub/PyGithub/blob/540a085001/github/InputGitTreeElement.py#L81
Je peux comprendre que passer un None
va à l'encontre du design. Je pense que quelque chose comme github.GithubObject.Null
pourrait être introduit pour dire explicitement que ce champ est null
. Il peut être utilisé partout où l'API GH accepte une valeur nulle.
Exemple
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
)
Cela supprimera my/dir/my_file.txt
Ma solution de contournement actuelle consiste à appuyer directement sur l'API pour créer un arbre (en utilisant des requêtes, en définissant sha=None
), obtenir l'arbre sha et l'utiliser avec pygithub pour mon flux de travail restant (committing, etc.).
S'il vous plaît laissez-moi savoir au cas où j'ai mal compris un aspect ou si quelque chose doit être développé.
En fait, NotSet est une classe à part entière qui n'a rien à voir avec None, donc si vous passez None, cela devrait fonctionner correctement.
Oh, attends, je vois. Nous affirmons que c'est un str! D'accord, d'accord, donc je pense que desserrer pour autoriser None est parfaitement bien alors, belle prise.
J'ai beaucoup de mal avec ce changement. J'ai apporté les modifications nécessaires, mais l'API create_git_tree() renvoie 422 GitRPC::BadObjectState ou une erreur générique 404 Not Found. Êtes-vous en mesure de fournir un exemple de travail par rapport à un dépôt public afin que je puisse récupérer les données de relecture pour le test unitaire ?
Mon code est pour un dépôt privé, je viens donc d'en créer une version allégée pour vous ici :
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)
L'une des raisons pour lesquelles j'ai également reçu 422 GitRPC::BadObjectState
était que je fournissais des noms de fichiers dans paths
qui n'existaient pas dans l'arborescence de base. Par exemple, essayez de corrompre 1 des noms de fichiers ci-dessus.
Je ne peux pas rendre mon référentiel de test public, mais voici la structure, configurez simplement les fichiers factices dans votre propre référentiel
pods/
raghav/
network/
resources.tf
Merci beaucoup! Je vais essayer ça dans les prochains jours. Peut-être sans les f-strings. :-)
@stevenk wahou ! merci d'avoir corrigé ça
cc @rohitpaulk
@stevenk Je crée un commit comme celui-ci, mais cela se commit même si le fichier diff est nul. S'il vous plaît, toute aide sur la façon de s'engager uniquement s'il y a des diff . Merci !
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 Les arbres SHA sont essentiellement des sommes de contrôle de tous les fichiers de votre référentiel, vous pouvez donc simplement vérifier s'ils correspondent.
Dans votre contexte, ce serait quelque chose comme :
if tree.sha != base_tree.sha:
# then commit
(Je ne me souviens pas de la méthode exacte utilisée pour aller chercher un sha, mais vous voyez l'idée)
Commentaire le plus utile
Merci beaucoup! Je vais essayer ça dans les prochains jours. Peut-être sans les f-strings. :-)