Python Gitlab提交创建功能遇文件重命名时失效问题求助
解决python-gitlab复制提交时文件重命名操作失败的问题
我通过GitLab派生(fork)创建了目标仓库,使用python-gitlab编写脚本同步源仓库的提交。脚本在处理文件修改、删除操作时能正常创建提交,但遇到文件重命名场景时失效,抛出错误:
gitlab.exceptions.GitlabCreateError: 400: A file with this name doesn't exist
原脚本代码:
def copying_commit(): tag = source_project.tags.get('v0.0.8') commit_sha = tag.commit['id'] source_commit = source_project.commits.get(commit_sha) destination_project = gl.projects.get(project_id) source_branch = 'sub_dev' # Initialize a list to store actions for the commit commit_actions = [] # Iterate through file changes and accumulate actions for file_change in source_commit.diff(): print(file_change) print(file_change['new_path']) print(file_change['old_path']) if file_change['deleted_file']: action_type = 'delete' elif file_change['new_file']: action_type = 'create' else: action_type = 'update' commit_actions.append({ 'action': action_type, 'file_path': file_change['new_path'] if action_type != 'delete' else file_change['old_path'], 'content': source_project.files.raw(file_path=file_change['new_path'], ref=source_branch_info.name).decode('UTF-8') if action_type != 'delete' else None }) commit = destination_project.commits.create({ 'branch': 'sub_dev', 'commit_message': f' v0.0.8 Merge changes from{source_project.web_url} {source_branch}', 'actions': commit_actions }) destination_project.tags.create({ 'tag_name': 'v0.0.8', 'ref': commit.id, 'message': f'Tag v0.0.8 for commit {commit.id}' })
问题原因
GitLab提交的diff中,文件重命名会同时返回old_path和new_path,且deleted_file、new_file都为false。原脚本会将这种情况判定为update操作,但目标仓库中不存在new_path对应的文件,导致执行update时触发文件不存在的错误。另外,GitLab API支持专门的rename动作来处理文件重命名,不需要传入文件内容。
修改后的脚本
def copying_commit(): tag = source_project.tags.get('v0.0.8') commit_sha = tag.commit['id'] source_commit = source_project.commits.get(commit_sha) destination_project = gl.projects.get(project_id) source_branch = 'sub_dev' # Initialize a list to store actions for the commit commit_actions = [] # Iterate through file changes and accumulate actions for file_change in source_commit.diff(): print(file_change) print(file_change['new_path']) print(file_change['old_path']) # 判断是否为文件重命名 if file_change['old_path'] != file_change['new_path'] and not file_change['deleted_file'] and not file_change['new_file']: action_type = 'rename' commit_actions.append({ 'action': action_type, 'file_path': file_change['new_path'], 'previous_path': file_change['old_path'] }) elif file_change['deleted_file']: action_type = 'delete' commit_actions.append({ 'action': action_type, 'file_path': file_change['old_path'] }) elif file_change['new_file']: action_type = 'create' commit_actions.append({ 'action': action_type, 'file_path': file_change['new_path'], 'content': source_project.files.raw(file_path=file_change['new_path'], ref=source_branch).decode('UTF-8') }) else: action_type = 'update' commit_actions.append({ 'action': action_type, 'file_path': file_change['new_path'], 'content': source_project.files.raw(file_path=file_change['new_path'], ref=source_branch).decode('UTF-8') }) commit = destination_project.commits.create({ 'branch': 'sub_dev', 'commit_message': f' v0.0.8 Merge changes from {source_project.web_url} {source_branch}', 'actions': commit_actions }) destination_project.tags.create({ 'tag_name': 'v0.0.8', 'ref': commit.id, 'message': f'Tag v0.0.8 for commit {commit.id}' })
修改说明
- 新增文件重命名判断逻辑:当
old_path与new_path不同,且既不是新文件也不是删除文件时,判定为重命名操作 - 重命名动作使用GitLab API的
rename类型,只需指定新路径file_path和原路径previous_path,无需传入文件内容 - 拆分不同动作的处理逻辑,避免原脚本中content赋值的冗余判断,同时修正了原脚本中
source_branch_info.name的笔误(改为source_branch)
内容的提问来源于stack exchange,提问作者Chitrangda Pandya
相关产品推荐
相关产品推荐

