-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathretag_szilank.py
128 lines (98 loc) · 5.47 KB
/
retag_szilank.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import git
import sys
class GitOps:
def __init__(self, repo_path, work_branch_name):
self.repo = git.Repo(repo_path)
self.zero_tag = None
self.distance_zero = 0
if not work_branch_name:
self.active_branch_name = self.repo.active_branch.name # master if you are on default
else:
self.active_branch_name = work_branch_name
self.rename_prefix = 'xx_'
self.tags = []
self.tags_detached = []
self.get_tag_lists()
# self.dump_tag_infos() # DEBUG only
if self.guess_zero_tag() is None:
print("No detached tags found. Exiting.")
sys.exit(1)
def is_tag_on_active_branch(self, tag):
active_branch_commit = self.repo.active_branch.commit
return self.repo.merge_base(active_branch_commit, tag.commit)[0].hexsha == tag.commit.hexsha
def get_tag_lists(self):
self.tags = sorted(self.repo.tags, key=lambda t: t.commit.committed_date, reverse=False)
# TODO, BUG: all tags appear detached even ones are attached to master...
# First detached should be tag: 0.4.2.9
# tag class type: git.refs.tag.TagReference
## if branch_head.tags and tag_name not in branch_head.tags:
## print("tag is not attached to branch head")
# self.tags_detached = [tag for tag in self.tags if tag.is_detached]
self.tags_detached = [tag for tag in self.tags if not self.is_tag_on_active_branch(tag)]
def guess_zero_tag(self):
if not self.is_tag_on_active_branch(self.tags[0]):
print("First tag is not on active branch. Exiting.")
return None
previous_tag = None
for tag in self.tags:
if not self.is_tag_on_active_branch(tag):
self.zero_tag = previous_tag
return True
else:
previous_tag = tag
return None # if there was no detached tag
def get_tag_distance_from_branch_head(self, tag):
return self.repo.head.commit.count() - tag.commit.count()
def get_distance_from_zero_tag(self, next_tag): # TODO
xxx self.zero_tag.commit.count() - next_tag.commit.count()
# get commit which is on active branch AND is in distance from zero. Search direction: forward
def get_commit_in_distance_from_zero(self, distance): # TODO
# zero_commit = self.repo.commit(self.zero_tag.commit)
zero_commit = self.zero_tag.commit
commits = list(self.repo.iter_commits(rev=self.repo.active_branch, max_count=distance + 1, first_parent=True, reverse=True))
# Check if the distance is within the range of available commits
if len(commits) <= distance or distance < 0:
print(f"Invalid distance: the repo has fewer than {distance+1} commits from zero.")
sys.exit(1)
# Return the commit at the specified distance
target_commit = commits[distance]
return target_commit
# def get_commit_distance(self, master_commit, detached_commit):
# # Get the commit history starting from the master branch
# commits = list(self.repo.iter_commits(master_commit))
# # Find the distance between the detached commit and master commit
# for i, commit in enumerate(commits):
# if commit.hexsha == detached_commit.hexsha:
# return i
# # If we get here, the detached commit isn't in the history of master
# raise ValueError("Detached commit not found in the history of the master branch.")
def rename_tag_with_prefix(self, original_tagname): # DONE
new_tag = f"{self.rename_prefix}{original_tagname}"
commit = self.repo.commit(original_tagname)
self.repo.create_tag(new_tag, commit)
self.repo.delete_tag(original_tagname)
return new_tag
def iterate_and_fix_on_detached_tags(self):
self.distance_zero = self.get_tag_distance_from_branch_head(self.zero_tag)
for tag in gg.tags_detached:
distance = self.get_distance_from_zero_tag(tag)
print(f"ZERO tag ({self.zero_tag.name}) commit hash: {self.zero_tag.commit.hexsha}")
print(f"tag: {tag.name}, distance from zero tag: {distance}")
actual_tagname = tag.name
# prefixed_tagname = self.rename_tag_with_prefix(actual_tagname) # DEBUG: put back, when commits are passing
active_commit = self.get_commit_in_distance_from_zero(distance)
print(f"detached tag commit: '{tag.commit.hexsha}', message: '{tag.commit.message.strip()}'\n")
print(f"onbranch commit: '{active_commit.hexsha}', message: '{active_commit.message.strip()}'\n")
print("==========================================================================")
# self.repo.git.create_tag(actual_tagname, active_commit) # DEBUG: put back, when commits are passing
# self.repo.git.tag('-d', prefixed_tagname) # DEBUG: put back, when commits are passing
def dump_tag_infos(self): # DONE
for tag in self.tags:
print(f"Normal tag: {tag.name}, Commit: {tag.commit}")
for tag in self.tags_detached:
print(f"Detached tag: {tag.name}, Commit: {tag.commit}, typeof class: {type(tag)}")
gg = GitOps(repo_path='/repo/github/szilank.code', work_branch_name='master')
gg.iterate_and_fix_on_detached_tags()
# gg.dump_tag_infos()