NikGapps 3.29__py3-none-any.whl → 3.31__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- NikGapps/build/Build.py +8 -8
- NikGapps/build/NikGappsManager.py +2 -2
- NikGapps/build/Release.py +6 -6
- NikGapps/build_config.py +11 -11
- NikGapps/cache.py +12 -12
- NikGapps/config/NikGappsConfig.py +15 -15
- NikGapps/copy_repos.py +2 -2
- NikGapps/helper/Assets.py +8 -8
- NikGapps/helper/Package.py +2 -6
- NikGapps/helper/compression/CompOps.py +6 -6
- NikGapps/helper/compression/Export.py +10 -10
- NikGapps/helper/git/TestGit.py +1 -1
- NikGapps/helper/overlay/ApkMetaInfo.py +1 -1
- NikGapps/helper/overlay/Manifest.py +1 -1
- NikGapps/helper/overlay/Overlay.py +1 -1
- NikGapps/helper/upload/CmdUpload.py +7 -7
- NikGapps/helper/upload/GoFileUpload.py +7 -7
- NikGapps/main.py +9 -9
- NikGapps/overlay_control.py +11 -10
- NikGapps/test.py +1 -20
- {NikGapps-3.29.dist-info → NikGapps-3.31.dist-info}/METADATA +4 -3
- NikGapps-3.31.dist-info/RECORD +65 -0
- NikGapps/build/NikGappsPackages.py +0 -916
- NikGapps/helper/B64.py +0 -34
- NikGapps/helper/C.py +0 -16
- NikGapps/helper/Cmd.py +0 -296
- NikGapps/helper/FileOp.py +0 -235
- NikGapps/helper/Json.py +0 -34
- NikGapps/helper/P.py +0 -23
- NikGapps/helper/Statics.py +0 -166
- NikGapps/helper/SystemStat.py +0 -103
- NikGapps/helper/T.py +0 -82
- NikGapps/helper/XmlOp.py +0 -40
- NikGapps/helper/compression/Modes.py +0 -4
- NikGapps/helper/compression/Tar.py +0 -25
- NikGapps/helper/compression/Zip.py +0 -97
- NikGapps/helper/compression/Zsh.py +0 -17
- NikGapps/helper/git/Git.py +0 -228
- NikGapps/helper/git/GitOperations.py +0 -118
- NikGapps/helper/git/GitStatics.py +0 -14
- NikGapps/helper/git/GithubManager.py +0 -21
- NikGapps/helper/git/GitlabManager.py +0 -265
- NikGapps/helper/upload/Upload.py +0 -125
- NikGapps/helper/web/Requests.py +0 -139
- NikGapps/helper/web/TelegramApi.py +0 -126
- NikGapps/helper/web/__init__.py +0 -0
- NikGapps-3.29.dist-info/RECORD +0 -89
- {NikGapps-3.29.dist-info → NikGapps-3.31.dist-info}/LICENSE +0 -0
- {NikGapps-3.29.dist-info → NikGapps-3.31.dist-info}/WHEEL +0 -0
- {NikGapps-3.29.dist-info → NikGapps-3.31.dist-info}/entry_points.txt +0 -0
- {NikGapps-3.29.dist-info → NikGapps-3.31.dist-info}/top_level.txt +0 -0
NikGapps/helper/git/Git.py
DELETED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
|
|
3
|
-
import git.exc
|
|
4
|
-
from git import Repo, Commit
|
|
5
|
-
from shutil import copyfile
|
|
6
|
-
from .. import Config
|
|
7
|
-
from ..FileOp import FileOp
|
|
8
|
-
from ..Assets import Assets
|
|
9
|
-
import os
|
|
10
|
-
import time
|
|
11
|
-
import datetime
|
|
12
|
-
from datetime import datetime
|
|
13
|
-
import pytz
|
|
14
|
-
from .GitStatics import GitStatics
|
|
15
|
-
from ..P import P
|
|
16
|
-
from ..T import T
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class Git:
|
|
20
|
-
|
|
21
|
-
def __init__(self, working_tree_dir):
|
|
22
|
-
os.environ["GIT_CLONE_PROTECTION_ACTIVE"] = 'false'
|
|
23
|
-
self.enable_push = Config.GIT_PUSH
|
|
24
|
-
self.working_tree_dir = working_tree_dir
|
|
25
|
-
self.repo_name = None
|
|
26
|
-
if FileOp.dir_exists(self.working_tree_dir):
|
|
27
|
-
self.repo = Repo(working_tree_dir)
|
|
28
|
-
|
|
29
|
-
def clone_repo(self, repo_url, branch="main", fresh_clone=True, commit_depth=1):
|
|
30
|
-
try:
|
|
31
|
-
t = T()
|
|
32
|
-
if fresh_clone:
|
|
33
|
-
# for fresh clone, we must clean the directory and clone again
|
|
34
|
-
if FileOp.dir_exists(self.working_tree_dir):
|
|
35
|
-
print(f"{self.working_tree_dir} already exists, deleting for a fresh clone!")
|
|
36
|
-
FileOp.remove_dir(self.working_tree_dir)
|
|
37
|
-
if commit_depth == 0:
|
|
38
|
-
P.green(f"git clone -b {branch} {repo_url}")
|
|
39
|
-
self.repo = git.Repo.clone_from(repo_url, self.working_tree_dir, branch=branch)
|
|
40
|
-
else:
|
|
41
|
-
P.green(f"git clone -b {branch} --depth={commit_depth} {repo_url}")
|
|
42
|
-
self.repo = git.Repo.clone_from(repo_url, self.working_tree_dir, branch=branch, depth=commit_depth)
|
|
43
|
-
|
|
44
|
-
else:
|
|
45
|
-
# if it is not a fresh clone, we only clone when directory doesn't exist
|
|
46
|
-
if not FileOp.dir_exists(self.working_tree_dir):
|
|
47
|
-
print(f"{self.working_tree_dir} doesn't exists, fresh clone is enforced!")
|
|
48
|
-
P.yellow(f"git clone -b {branch} --depth={commit_depth} {repo_url}")
|
|
49
|
-
self.repo = git.Repo.clone_from(repo_url, self.working_tree_dir, branch=branch, depth=commit_depth)
|
|
50
|
-
t.taken(f"Time taken to clone -b {branch} {repo_url}")
|
|
51
|
-
self.update_repo_name(repo_url)
|
|
52
|
-
assert self.repo.__class__ is Repo # clone an existing repository
|
|
53
|
-
assert Repo.init(self.working_tree_dir).__class__ is Repo
|
|
54
|
-
return True
|
|
55
|
-
except Exception as e:
|
|
56
|
-
print("Exception caught while cloning the repo: " + str(e))
|
|
57
|
-
return False
|
|
58
|
-
|
|
59
|
-
# this will return commits 21-30 from the commit list as traversed backwards master
|
|
60
|
-
# ten_commits_past_twenty = list(repo.iter_commits('master', max_count=10, skip=20))
|
|
61
|
-
# assert len(ten_commits_past_twenty) == 10
|
|
62
|
-
# assert fifty_first_commits[20:30] == ten_commits_past_twenty
|
|
63
|
-
# repo = git.Repo.clone_from(repo_url, working_tree_dir, branch='master')
|
|
64
|
-
def get_latest_commit_date(self, branch=None, filter_key=None):
|
|
65
|
-
tz_london = pytz.timezone('Europe/London')
|
|
66
|
-
try:
|
|
67
|
-
if branch is not None:
|
|
68
|
-
commits = list(self.repo.iter_commits(branch, max_count=50))
|
|
69
|
-
else:
|
|
70
|
-
commits = list(self.repo.iter_commits('master', max_count=50))
|
|
71
|
-
except git.exc.GitCommandError:
|
|
72
|
-
if branch == "master":
|
|
73
|
-
branch = "main"
|
|
74
|
-
commits = list(self.repo.iter_commits(branch, max_count=50))
|
|
75
|
-
|
|
76
|
-
for commit in commits:
|
|
77
|
-
commit: Commit
|
|
78
|
-
# if filter_key = 10, it will look for commits that starts with 10
|
|
79
|
-
# failing will continue looking for latest available commit that starts with 10
|
|
80
|
-
if filter_key is not None and not str(commit.message).startswith(filter_key + ":"):
|
|
81
|
-
continue
|
|
82
|
-
time_in_string = str(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(commit.committed_date)))
|
|
83
|
-
time_in_object = datetime.strptime(time_in_string, '%Y-%m-%d %H:%M:%S')
|
|
84
|
-
london_time_in_object = time_in_object.astimezone(tz_london)
|
|
85
|
-
london_time_in_string = london_time_in_object.strftime('%Y-%m-%d %H:%M:%S')
|
|
86
|
-
commit_datetime = datetime.strptime(london_time_in_string, '%Y-%m-%d %H:%M:%S')
|
|
87
|
-
return commit_datetime
|
|
88
|
-
return None
|
|
89
|
-
|
|
90
|
-
def update_repo_name(self, git_url):
|
|
91
|
-
git_pattern = re.compile(r'git@[^:]+:[^/]+/(.+)\.git')
|
|
92
|
-
https_pattern = re.compile(r'https?://[^/]+/[^/]+/(.+)\.git')
|
|
93
|
-
match = git_pattern.match(git_url) or https_pattern.match(git_url)
|
|
94
|
-
if match:
|
|
95
|
-
self.repo_name = match.group(1)
|
|
96
|
-
else:
|
|
97
|
-
raise ValueError("Invalid Git URL")
|
|
98
|
-
|
|
99
|
-
def get_file_commit_date(self, file_path, str_format="%y%m%d%H%M", skip_containing=None):
|
|
100
|
-
commits_touching_path = list(self.repo.iter_commits(paths=file_path))
|
|
101
|
-
if commits_touching_path:
|
|
102
|
-
for commit in commits_touching_path:
|
|
103
|
-
if skip_containing is not None and str(skip_containing).lower() in commit.message.lower():
|
|
104
|
-
P.blue(f"Skipping commit ({commit.hexsha[:7]}): "
|
|
105
|
-
f"{commit.message} as it contains '{skip_containing}'")
|
|
106
|
-
continue
|
|
107
|
-
P.green(f"Commit ({commit.hexsha[:7]}): {commit.message} found for {file_path}")
|
|
108
|
-
return commit.committed_datetime.strftime(str_format)
|
|
109
|
-
else:
|
|
110
|
-
return None
|
|
111
|
-
|
|
112
|
-
def get_changed_files(self):
|
|
113
|
-
files_list = []
|
|
114
|
-
files = self.repo.git.diff(None, name_only=True)
|
|
115
|
-
if files != "":
|
|
116
|
-
for f in files.split('\n'):
|
|
117
|
-
files_list.append(f)
|
|
118
|
-
if self.repo.untracked_files.__len__() > 0:
|
|
119
|
-
for f in self.repo.untracked_files:
|
|
120
|
-
files_list.append(f)
|
|
121
|
-
return files_list
|
|
122
|
-
|
|
123
|
-
def due_changes(self):
|
|
124
|
-
files = self.repo.git.diff(None, name_only=True)
|
|
125
|
-
if files != "":
|
|
126
|
-
if files.split('\n').__len__() > 0:
|
|
127
|
-
return True
|
|
128
|
-
if self.repo.untracked_files.__len__() > 0:
|
|
129
|
-
return True
|
|
130
|
-
return False
|
|
131
|
-
|
|
132
|
-
def git_push(self, commit_message, push_untracked_files=False, debug=False, rebase=False, pull_first=False,
|
|
133
|
-
post_buffer=None):
|
|
134
|
-
if not self.enable_push:
|
|
135
|
-
print("Git push is disabled, skipping push!")
|
|
136
|
-
return False
|
|
137
|
-
try:
|
|
138
|
-
origin = self.repo.remote(name='origin')
|
|
139
|
-
if post_buffer is not None:
|
|
140
|
-
self.repo.git.config('http.postBuffer', post_buffer)
|
|
141
|
-
if self.repo.is_dirty(untracked_files=True):
|
|
142
|
-
self.repo.git.add(u=True)
|
|
143
|
-
if push_untracked_files:
|
|
144
|
-
self.repo.git.add(A=True)
|
|
145
|
-
if commit_message is None:
|
|
146
|
-
commit_message = "Auto Commit"
|
|
147
|
-
self.repo.index.commit(commit_message)
|
|
148
|
-
if pull_first:
|
|
149
|
-
origin.fetch(self.repo.active_branch.name)
|
|
150
|
-
origin.pull(self.repo.active_branch.name)
|
|
151
|
-
if rebase:
|
|
152
|
-
origin.fetch(self.repo.active_branch.name)
|
|
153
|
-
try:
|
|
154
|
-
self.repo.git.pull('--rebase')
|
|
155
|
-
except git.GitCommandError as e:
|
|
156
|
-
print(f"Error during rebase: {e}")
|
|
157
|
-
return False
|
|
158
|
-
if debug:
|
|
159
|
-
remotes = self.repo.remotes
|
|
160
|
-
for remote in remotes:
|
|
161
|
-
print(f"Remote name: {remote.name}")
|
|
162
|
-
for url in remote.urls:
|
|
163
|
-
print(f"URL: {url}")
|
|
164
|
-
P.blue(self.repo.git.status())
|
|
165
|
-
push_info = origin.push(self.repo.active_branch.name)
|
|
166
|
-
for info in push_info:
|
|
167
|
-
if info.flags & (git.PushInfo.REMOTE_REJECTED | git.PushInfo.ERROR):
|
|
168
|
-
print(f"Push failed for ref {info.local_ref}: {info.summary}")
|
|
169
|
-
if info.summary.__contains__("remote rejected") and info.summary.__contains__(
|
|
170
|
-
"is at") and info.summary.__contains__("but expected"):
|
|
171
|
-
print("Remote rejected, trying to pull!")
|
|
172
|
-
origin.fetch(self.repo.active_branch.name)
|
|
173
|
-
origin.pull(self.repo.active_branch.name)
|
|
174
|
-
# rebase if this fails.
|
|
175
|
-
push_info = origin.push(self.repo.active_branch.name)
|
|
176
|
-
for nested_info in push_info:
|
|
177
|
-
if nested_info.flags & (git.PushInfo.REMOTE_REJECTED | git.PushInfo.ERROR):
|
|
178
|
-
print(f"Push failed for ref {nested_info.local_ref}: {nested_info.summary}")
|
|
179
|
-
return False
|
|
180
|
-
return False
|
|
181
|
-
|
|
182
|
-
print("Pushed to origin:", commit_message)
|
|
183
|
-
return True
|
|
184
|
-
|
|
185
|
-
except git.exc.GitCommandError as e:
|
|
186
|
-
if "failed to push some refs" in e.stderr: # Check for the specific error
|
|
187
|
-
self.repo.git.pull("origin", "main") # Pull changes from remote
|
|
188
|
-
self.repo.git.push() # Retry the push
|
|
189
|
-
else:
|
|
190
|
-
print(f"Git error: {e}")
|
|
191
|
-
raise e
|
|
192
|
-
|
|
193
|
-
except Exception as e:
|
|
194
|
-
print(f"Unexpected error: {e}")
|
|
195
|
-
return False
|
|
196
|
-
|
|
197
|
-
def update_changelog(self):
|
|
198
|
-
source_file = Assets.changelog
|
|
199
|
-
dest_file = GitStatics.website_repo_dir + os.path.sep + "_data" + os.path.sep + "changelogs.yaml"
|
|
200
|
-
copyfile(source_file, dest_file)
|
|
201
|
-
if self.due_changes():
|
|
202
|
-
print("Updating the changelog to the website")
|
|
203
|
-
self.git_push("Update Changelog")
|
|
204
|
-
else:
|
|
205
|
-
print("There is no changelog to update!")
|
|
206
|
-
|
|
207
|
-
def update_config_changes(self, message):
|
|
208
|
-
if self.due_changes():
|
|
209
|
-
print(message)
|
|
210
|
-
self.git_push(message, push_untracked_files=True)
|
|
211
|
-
else:
|
|
212
|
-
print("There is nothing to update!")
|
|
213
|
-
|
|
214
|
-
def update_repo_changes(self, message):
|
|
215
|
-
if self.due_changes():
|
|
216
|
-
P.green(message)
|
|
217
|
-
self.git_push(message, push_untracked_files=True)
|
|
218
|
-
else:
|
|
219
|
-
P.red("There is nothing to update!")
|
|
220
|
-
|
|
221
|
-
def get_status(self, path):
|
|
222
|
-
changed = [item.a_path for item in self.repo.index.diff(None)]
|
|
223
|
-
if path in self.repo.untracked_files:
|
|
224
|
-
return 'untracked'
|
|
225
|
-
elif path in changed:
|
|
226
|
-
return 'modified'
|
|
227
|
-
else:
|
|
228
|
-
return 'don''t care'
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from ..FileOp import FileOp
|
|
3
|
-
from .Git import Git
|
|
4
|
-
from .GitStatics import GitStatics
|
|
5
|
-
from ..Statics import Statics
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class GitOperations:
|
|
9
|
-
|
|
10
|
-
@staticmethod
|
|
11
|
-
def setup_tracker_repo(fresh_clone=True):
|
|
12
|
-
return GitOperations.setup_repo(GitStatics.tracker_repo_dir, GitStatics.tracker_repo_url, "main", fresh_clone)
|
|
13
|
-
|
|
14
|
-
@staticmethod
|
|
15
|
-
def setup_repo(repo_dir, repo_url, branch="main", fresh_clone=True, commit_depth=50):
|
|
16
|
-
print()
|
|
17
|
-
print("Repo Dir: " + repo_dir)
|
|
18
|
-
repo = Git(repo_dir)
|
|
19
|
-
result = repo.clone_repo(repo_url, branch=branch, fresh_clone=fresh_clone, commit_depth=commit_depth)
|
|
20
|
-
return repo if result else None
|
|
21
|
-
|
|
22
|
-
@staticmethod
|
|
23
|
-
def clone_overlay_repo(android_version, fresh_clone=False, branch="main", source=False, enable_push=False):
|
|
24
|
-
if float(android_version) > 12:
|
|
25
|
-
overlay_source_dir = (Statics.pwd + Statics.dir_sep + f"overlays_{android_version}"
|
|
26
|
-
+ ("_source" if source else ""))
|
|
27
|
-
overlay_source_repo = (("git@gitlab.com:nikgapps/" if enable_push else "https://gitlab.com/nikgapps/")
|
|
28
|
-
+ f"overlays_{android_version}"
|
|
29
|
-
+ ("_source" if source else "") + ".git")
|
|
30
|
-
return GitOperations.setup_repo(overlay_source_dir, overlay_source_repo, branch, fresh_clone)
|
|
31
|
-
else:
|
|
32
|
-
print(f"Cloning Overlay repo not needed for android {android_version}")
|
|
33
|
-
return None
|
|
34
|
-
|
|
35
|
-
@staticmethod
|
|
36
|
-
def clone_apk_repo(android_version, arch="arm64", fresh_clone=False, branch="main",
|
|
37
|
-
cached=False, use_ssh_clone=False):
|
|
38
|
-
arch = "" if arch == "arm64" else "_" + arch
|
|
39
|
-
cache = "_cached" if cached else ""
|
|
40
|
-
apk_source_directory = Statics.pwd + Statics.dir_sep + str(android_version) + arch + cache
|
|
41
|
-
apk_source_repo = (GitStatics.apk_source_repo_ssh if use_ssh_clone else GitStatics.apk_source_repo) + str(
|
|
42
|
-
android_version) + arch + cache + ".git"
|
|
43
|
-
return GitOperations.setup_repo(apk_source_directory, apk_source_repo, branch, fresh_clone, commit_depth=1)
|
|
44
|
-
|
|
45
|
-
# Following method is new method of cloning the apk source from Gitlab - based on release type
|
|
46
|
-
@staticmethod
|
|
47
|
-
def clone_apk_source(android_version, arch="arm64", release_type="stable", fresh_clone=False, cached=False,
|
|
48
|
-
use_ssh_clone=False):
|
|
49
|
-
url = f"{android_version}{('_' + arch if arch != 'arm64' else '')}_{release_type}"
|
|
50
|
-
url = url + ("_cached" if cached else "")
|
|
51
|
-
return GitOperations.clone_apk_url(url, fresh_clone, use_ssh_clone)
|
|
52
|
-
|
|
53
|
-
@staticmethod
|
|
54
|
-
def clone_apk_url(url, fresh_clone=False, use_ssh_clone=False):
|
|
55
|
-
apk_source_directory = Statics.pwd + Statics.dir_sep + url
|
|
56
|
-
apk_source_repo = ((GitStatics.apk_source_repo_ssh if use_ssh_clone else GitStatics.apk_source_repo) + url
|
|
57
|
-
+ ".git")
|
|
58
|
-
return GitOperations.setup_repo(apk_source_directory, apk_source_repo, branch="main", fresh_clone=fresh_clone,
|
|
59
|
-
commit_depth=1)
|
|
60
|
-
|
|
61
|
-
@staticmethod
|
|
62
|
-
def get_last_commit_date(branch, repo_dir=Statics.cwd, repo_url=None, android_version=None, use_ssh_clone=False):
|
|
63
|
-
last_commit_datetime = None
|
|
64
|
-
if android_version is not None:
|
|
65
|
-
repository = GitOperations.clone_apk_repo(android_version, branch=branch, use_ssh_clone=use_ssh_clone)
|
|
66
|
-
else:
|
|
67
|
-
repository = Git(repo_dir)
|
|
68
|
-
if repo_url is not None:
|
|
69
|
-
repository.clone_repo(repo_url=repo_url, fresh_clone=False, branch=branch)
|
|
70
|
-
if repository is not None:
|
|
71
|
-
last_commit_datetime = repository.get_latest_commit_date(branch=branch)
|
|
72
|
-
return last_commit_datetime
|
|
73
|
-
|
|
74
|
-
@staticmethod
|
|
75
|
-
def get_release_repo(release_type):
|
|
76
|
-
release_repo = Git(GitStatics.release_history_dir)
|
|
77
|
-
if not FileOp.dir_exists(GitStatics.release_history_dir):
|
|
78
|
-
if release_type == "canary":
|
|
79
|
-
GitStatics.release_repo_url = "git@github.com:nikgapps/canary-release.git"
|
|
80
|
-
release_repo.clone_repo(GitStatics.release_repo_url, branch="master", commit_depth=50)
|
|
81
|
-
if not FileOp.dir_exists(GitStatics.release_history_dir):
|
|
82
|
-
print(GitStatics.release_history_dir + " doesn't exist!")
|
|
83
|
-
return release_repo
|
|
84
|
-
|
|
85
|
-
@staticmethod
|
|
86
|
-
def get_website_repo_for_changelog(repo_dir=GitStatics.website_repo_dir, repo_url=GitStatics.website_repo_url,
|
|
87
|
-
branch="main"):
|
|
88
|
-
repo = Git(repo_dir)
|
|
89
|
-
if repo_url is not None:
|
|
90
|
-
repo.clone_repo(repo_url=repo_url, fresh_clone=False, branch=branch)
|
|
91
|
-
if not FileOp.dir_exists(GitStatics.website_repo_dir):
|
|
92
|
-
print(f"Repo {repo_dir} doesn't exist!")
|
|
93
|
-
return repo
|
|
94
|
-
|
|
95
|
-
@staticmethod
|
|
96
|
-
def mark_a_release(android_version, release_type):
|
|
97
|
-
tracker_repo = GitOperations.setup_tracker_repo(False)
|
|
98
|
-
if tracker_repo is not None:
|
|
99
|
-
release_tracker = tracker_repo.working_tree_dir + Statics.dir_sep + "release_tracker.json"
|
|
100
|
-
decoded_hand = {}
|
|
101
|
-
if FileOp.file_exists(release_tracker):
|
|
102
|
-
with open(release_tracker, "r") as file:
|
|
103
|
-
decoded_hand = json.load(file)
|
|
104
|
-
if release_type not in decoded_hand:
|
|
105
|
-
decoded_hand[release_type] = {}
|
|
106
|
-
decoded_hand[release_type][android_version] = Statics.time
|
|
107
|
-
else:
|
|
108
|
-
decoded_hand[release_type] = {}
|
|
109
|
-
decoded_hand[release_type][android_version] = Statics.time
|
|
110
|
-
print(f"Marking a release with {decoded_hand}")
|
|
111
|
-
with open(release_tracker, "w") as file:
|
|
112
|
-
json.dump(decoded_hand, file, indent=2, sort_keys=True)
|
|
113
|
-
if tracker_repo.due_changes():
|
|
114
|
-
tracker_repo.git_push(
|
|
115
|
-
f"Updated release_tracker.json with latest {release_type} release date: " + Statics.time,
|
|
116
|
-
pull_first=True)
|
|
117
|
-
else:
|
|
118
|
-
print("No changes to commit!")
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
from ..Statics import Statics
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class GitStatics:
|
|
5
|
-
tracker_repo_url = "git@github.com:nikgapps/tracker.git"
|
|
6
|
-
tracker_repo_dir = Statics.pwd + Statics.dir_sep + "tracker"
|
|
7
|
-
apk_source_repo_ssh = f"git@gitlab.com:nikgapps/"
|
|
8
|
-
apk_source_repo = f"https://gitlab.com/nikgapps/"
|
|
9
|
-
release_repo_url = "git@github.com:nikgapps/release.git"
|
|
10
|
-
release_history_dir = Statics.pwd + Statics.dir_sep + "release"
|
|
11
|
-
website_repo_url = "git@github.com:nikgapps/nikgapps.github.io.git"
|
|
12
|
-
website_repo_dir = Statics.pwd + Statics.dir_sep + "nikgapps.github.io"
|
|
13
|
-
config_repo_dir = Statics.pwd + Statics.dir_sep + "config"
|
|
14
|
-
config_repo_url = "git@github.com:nikgapps/config.git"
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
from github import Github
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class GithubManager:
|
|
5
|
-
|
|
6
|
-
def __init__(self, token):
|
|
7
|
-
self.g = Github(token)
|
|
8
|
-
self.user = self.g.get_user()
|
|
9
|
-
|
|
10
|
-
def get_user(self):
|
|
11
|
-
return self.g.get_user()
|
|
12
|
-
|
|
13
|
-
def get_repos(self):
|
|
14
|
-
return self.user.get_repos()
|
|
15
|
-
|
|
16
|
-
def create_repo(self, repo_name):
|
|
17
|
-
return self.user.create_repo(repo_name)
|
|
18
|
-
|
|
19
|
-
@staticmethod
|
|
20
|
-
def create_issue(repo, issue_title, issue_body):
|
|
21
|
-
return repo.create_issue(title=issue_title, body=issue_body)
|
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
import math
|
|
2
|
-
import shutil
|
|
3
|
-
import time
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
|
|
6
|
-
import gitlab
|
|
7
|
-
|
|
8
|
-
from NikGapps.helper.FileOp import FileOp
|
|
9
|
-
from NikGapps.helper.P import P
|
|
10
|
-
from NikGapps.helper.Statics import Statics
|
|
11
|
-
from NikGapps.helper.git.GitOperations import GitOperations
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class GitLabManager:
|
|
15
|
-
def __init__(self, gitlab_url='https://gitlab.com', private_token=None):
|
|
16
|
-
self.token = private_token
|
|
17
|
-
self.gl = gitlab.Gitlab(gitlab_url, private_token=private_token)
|
|
18
|
-
self.gl.auth()
|
|
19
|
-
|
|
20
|
-
def fetch_user_details(self, user_id):
|
|
21
|
-
"""Fetches user details for a specified user ID."""
|
|
22
|
-
user = self.gl.users.get(user_id)
|
|
23
|
-
return user
|
|
24
|
-
|
|
25
|
-
def create_repository(self, project_name, provide_owner_access=False, user_id=8064473, visibility='public'):
|
|
26
|
-
"""Creates a new repository with the given project name."""
|
|
27
|
-
project = self.gl.projects.create({'name': project_name, 'visibility': visibility})
|
|
28
|
-
if provide_owner_access:
|
|
29
|
-
self.provide_owner_access(project_id=project.id, user_id=user_id)
|
|
30
|
-
self.create_and_commit_readme(project_id=project.id)
|
|
31
|
-
return project
|
|
32
|
-
|
|
33
|
-
def create_lfs_repository(self, project_name, provide_owner_access=False, user_id=8064473, visibility='public',
|
|
34
|
-
extn_list=None):
|
|
35
|
-
"""Creates a new repository with the given project name and attributes."""
|
|
36
|
-
if extn_list is None:
|
|
37
|
-
extn_list = []
|
|
38
|
-
project = self.gl.projects.create({'name': project_name, 'visibility': visibility})
|
|
39
|
-
if provide_owner_access:
|
|
40
|
-
self.provide_owner_access(project_id=project.id, user_id=user_id)
|
|
41
|
-
self.create_and_commit_readme(project_id=project.id)
|
|
42
|
-
gitattributes = ""
|
|
43
|
-
for extn in extn_list:
|
|
44
|
-
gitattributes += f"*.{extn} filter=lfs diff=lfs merge=lfs -text\n"
|
|
45
|
-
self.create_and_commit_file(project_id=project.id, file_path=".gitattributes", content=gitattributes)
|
|
46
|
-
return project
|
|
47
|
-
|
|
48
|
-
def provide_owner_access(self, project_id, user_id):
|
|
49
|
-
"""Provides owner access to a repository for a particular user."""
|
|
50
|
-
project = self.gl.projects.get(project_id)
|
|
51
|
-
member = project.members.create({
|
|
52
|
-
'user_id': user_id,
|
|
53
|
-
'access_level': 50
|
|
54
|
-
})
|
|
55
|
-
P.green(f"Owner access provided to user with ID {user_id}.")
|
|
56
|
-
return member
|
|
57
|
-
|
|
58
|
-
def get_project(self, project_name):
|
|
59
|
-
# Fetch all projects for the current user
|
|
60
|
-
projects = self.gl.projects.list(owned=True, all=True)
|
|
61
|
-
|
|
62
|
-
# Print details of each project
|
|
63
|
-
for project in projects:
|
|
64
|
-
if project.path == project_name:
|
|
65
|
-
return project
|
|
66
|
-
return None
|
|
67
|
-
|
|
68
|
-
def create_and_commit_readme(self, project_id, branch_name="main", content="# Welcome to your new project"):
|
|
69
|
-
"""Creates a README.md file and commits it to the specified repository."""
|
|
70
|
-
project = self.gl.projects.get(project_id)
|
|
71
|
-
commit_data = {
|
|
72
|
-
'branch': branch_name,
|
|
73
|
-
'commit_message': 'Add README.md',
|
|
74
|
-
'actions': [
|
|
75
|
-
{
|
|
76
|
-
'action': 'create',
|
|
77
|
-
'file_path': 'README.md',
|
|
78
|
-
'content': content
|
|
79
|
-
}
|
|
80
|
-
]
|
|
81
|
-
}
|
|
82
|
-
commit = project.commits.create(commit_data)
|
|
83
|
-
P.green(f"README.md created and committed to the repository {project.name}.")
|
|
84
|
-
# print(commit)
|
|
85
|
-
return commit
|
|
86
|
-
|
|
87
|
-
def create_and_commit_file(self, project_id, branch_name="main", file_path="file.txt", content=""):
|
|
88
|
-
"""Creates a file and commits it to the specified repository."""
|
|
89
|
-
project = self.gl.projects.get(project_id)
|
|
90
|
-
commit_data = {
|
|
91
|
-
'branch': branch_name,
|
|
92
|
-
'commit_message': f'Add {file_path}',
|
|
93
|
-
'actions': [
|
|
94
|
-
{
|
|
95
|
-
'action': 'create',
|
|
96
|
-
'file_path': file_path,
|
|
97
|
-
'content': content
|
|
98
|
-
}
|
|
99
|
-
]
|
|
100
|
-
}
|
|
101
|
-
commit = project.commits.create(commit_data)
|
|
102
|
-
P.green(f"{file_path} created and committed to the repository {project.name}.")
|
|
103
|
-
# print(commit)
|
|
104
|
-
return commit
|
|
105
|
-
|
|
106
|
-
def create_gitlab_repository(self, project_name, visibility='public'):
|
|
107
|
-
try:
|
|
108
|
-
project = self.gl.projects.create({'name': project_name, 'visibility': visibility})
|
|
109
|
-
return project.web_url
|
|
110
|
-
except Exception as e:
|
|
111
|
-
raise Exception(f"Failed to create GitLab repository: {e}")
|
|
112
|
-
|
|
113
|
-
def get_repository_users_with_access_levels(self, project_id):
|
|
114
|
-
access_levels = {
|
|
115
|
-
10: 'Guest',
|
|
116
|
-
20: 'Reporter',
|
|
117
|
-
30: 'Developer',
|
|
118
|
-
40: 'Maintainer',
|
|
119
|
-
50: 'Owner'
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
project = self.gl.projects.get(project_id)
|
|
123
|
-
members = project.members.list(all=True)
|
|
124
|
-
user_access_levels = [(member.username, member.access_level, access_levels.get(member.access_level, 'Unknown'))
|
|
125
|
-
for member in
|
|
126
|
-
members]
|
|
127
|
-
|
|
128
|
-
return user_access_levels
|
|
129
|
-
|
|
130
|
-
def list_projects_with_ids(self, print_details=False):
|
|
131
|
-
namespace_name = "nikgapps"
|
|
132
|
-
# Fetch all projects for the current user
|
|
133
|
-
projects = self.gl.projects.list(owned=True, all=True)
|
|
134
|
-
|
|
135
|
-
# Print details of each project
|
|
136
|
-
for project in projects:
|
|
137
|
-
if not print_details:
|
|
138
|
-
return projects
|
|
139
|
-
project_details = self.gl.projects.get(project.id, statistics=True)
|
|
140
|
-
storage_size = math.ceil(project_details.statistics["storage_size"] / (1024 ** 2) * 100) / 100
|
|
141
|
-
print(f'Project Name: {project.name}, Project ID: {project.id}, Namespace: {project.namespace["path"]}, '
|
|
142
|
-
f'Storage Size: {storage_size} MB')
|
|
143
|
-
return projects
|
|
144
|
-
|
|
145
|
-
def find_project_allocated_size(self, repo_name):
|
|
146
|
-
project = self.get_project(repo_name)
|
|
147
|
-
project_details = self.gl.projects.get(project.id, statistics=True)
|
|
148
|
-
return math.ceil(project_details.statistics["storage_size"] / (1024 ** 2) * 100) / 100
|
|
149
|
-
|
|
150
|
-
def delete_project(self, project_id):
|
|
151
|
-
try:
|
|
152
|
-
project = self.gl.projects.get(project_id)
|
|
153
|
-
project_name = project.name
|
|
154
|
-
project_path = project.path
|
|
155
|
-
project.delete()
|
|
156
|
-
print(f"Project with id {project_id}, name {project_name} and path {project_path} deleted successfully.")
|
|
157
|
-
except Exception as e:
|
|
158
|
-
print(f"Failed to delete project {project_id}: {e}")
|
|
159
|
-
|
|
160
|
-
def rename_repository(self, repo_name, new_repo_name=None):
|
|
161
|
-
project = self.get_project(repo_name)
|
|
162
|
-
if new_repo_name is None:
|
|
163
|
-
new_repo_name = f"{repo_name}_{time.strftime('%Y%m%d')}"
|
|
164
|
-
new_project = self.get_project(new_repo_name)
|
|
165
|
-
if new_project is not None:
|
|
166
|
-
P.red(f"Project {new_repo_name} already exists. Deleting...")
|
|
167
|
-
self.delete_project(new_project.id)
|
|
168
|
-
project.name = new_repo_name
|
|
169
|
-
project.path = new_repo_name
|
|
170
|
-
P.yellow(f"Repository {repo_name} renaming to {new_repo_name}.")
|
|
171
|
-
project.save()
|
|
172
|
-
P.green(f"Repository {repo_name} renamed to {new_repo_name}.")
|
|
173
|
-
return project
|
|
174
|
-
|
|
175
|
-
def reset_repository(self, repo_name, gitattributes=None, user_id=8064473, sleep_for=10, delete_only=False):
|
|
176
|
-
try:
|
|
177
|
-
print(f"Resetting repository {repo_name}...")
|
|
178
|
-
project = self.get_project(repo_name)
|
|
179
|
-
self.delete_project(project.id)
|
|
180
|
-
if not delete_only:
|
|
181
|
-
P.red(f"Waiting for {sleep_for} seconds for the project to be completely deleted...")
|
|
182
|
-
time.sleep(sleep_for)
|
|
183
|
-
project = self.create_repository(repo_name, provide_owner_access=True, user_id=user_id)
|
|
184
|
-
if gitattributes is not None:
|
|
185
|
-
commit = self.create_and_commit_file(project_id=project.id, file_path=".gitattributes",
|
|
186
|
-
content=gitattributes)
|
|
187
|
-
# print(commit)
|
|
188
|
-
return project
|
|
189
|
-
except Exception as e:
|
|
190
|
-
print(f"Failed to reset repository: {e}")
|
|
191
|
-
return None
|
|
192
|
-
|
|
193
|
-
def reset_repository_storage(self, repo_name, user_id=8064473, sleep_for=10, storage_cap=7500, gitattributes=None,
|
|
194
|
-
method="rename"):
|
|
195
|
-
old_project = self.get_project(repo_name)
|
|
196
|
-
project_details = self.gl.projects.get(old_project.id, statistics=True)
|
|
197
|
-
storage_size = math.ceil(project_details.statistics["storage_size"] / (1024 ** 2) * 100) / 100
|
|
198
|
-
if storage_size > storage_cap:
|
|
199
|
-
print(f"Storage size of {storage_size} MB exceeds the limit of {storage_cap} MB "
|
|
200
|
-
f"for project id {old_project.id}. Resetting...")
|
|
201
|
-
old_repo_dir = Statics.pwd + Statics.dir_sep + f"{repo_name}_old"
|
|
202
|
-
old_repo = GitOperations.setup_repo(repo_dir=f"{old_repo_dir}", repo_url=project_details.ssh_url_to_repo)
|
|
203
|
-
match method.lower():
|
|
204
|
-
case "rename":
|
|
205
|
-
old_project = self.rename_repository(repo_name)
|
|
206
|
-
new_project = self.create_repository(repo_name, provide_owner_access=True, user_id=user_id)
|
|
207
|
-
case _:
|
|
208
|
-
new_project = self.reset_repository(repo_name, user_id=user_id, sleep_for=sleep_for,
|
|
209
|
-
gitattributes=gitattributes)
|
|
210
|
-
new_repo_dir = Statics.pwd + Statics.dir_sep + f"{repo_name}_new"
|
|
211
|
-
new_repo = GitOperations.setup_repo(repo_dir=f"{new_repo_dir}", repo_url=project_details.ssh_url_to_repo)
|
|
212
|
-
for item in Path(old_repo.working_tree_dir).rglob('*'):
|
|
213
|
-
if '.git' in item.parts:
|
|
214
|
-
continue
|
|
215
|
-
destination = Path(new_repo.working_tree_dir) / item.relative_to(Path(old_repo.working_tree_dir))
|
|
216
|
-
if item.is_dir():
|
|
217
|
-
destination.mkdir(parents=True, exist_ok=True)
|
|
218
|
-
else:
|
|
219
|
-
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
220
|
-
print(f"Copying {item} to {destination}")
|
|
221
|
-
shutil.copy2(item, destination)
|
|
222
|
-
new_repo.git_push("Initial Commit", push_untracked_files=True)
|
|
223
|
-
project_details = self.gl.projects.get(new_project.id, statistics=True)
|
|
224
|
-
storage_size = math.ceil(project_details.statistics["storage_size"] / (1024 ** 2) * 100) / 100
|
|
225
|
-
print(f"Repository storage for project id {new_project.id} reset successfully. "
|
|
226
|
-
f"New storage size: {storage_size} MB")
|
|
227
|
-
FileOp.remove_dir(old_repo.working_tree_dir)
|
|
228
|
-
FileOp.remove_dir(new_repo.working_tree_dir)
|
|
229
|
-
match method.lower():
|
|
230
|
-
case "rename":
|
|
231
|
-
self.delete_project(old_project.id)
|
|
232
|
-
else:
|
|
233
|
-
print(f"Storage size of {storage_size} MB is within the limit of {storage_cap} MB. No action required.")
|
|
234
|
-
|
|
235
|
-
def copy_repository(self, source_repo_name, target_repo_name, user_id=8064473, override_target=False):
|
|
236
|
-
project = self.get_project(source_repo_name)
|
|
237
|
-
if project is None:
|
|
238
|
-
print(f"Project {source_repo_name} does not exist. Exiting...")
|
|
239
|
-
return
|
|
240
|
-
old_repo_dir = Statics.pwd + Statics.dir_sep + f"{source_repo_name}_old"
|
|
241
|
-
old_repo = GitOperations.setup_repo(repo_dir=f"{old_repo_dir}", repo_url=project.ssh_url_to_repo)
|
|
242
|
-
if override_target:
|
|
243
|
-
target_project = self.get_project(target_repo_name)
|
|
244
|
-
if target_project is not None:
|
|
245
|
-
P.red(f"Project {target_repo_name} already exists. Deleting...")
|
|
246
|
-
self.delete_project(target_project.id)
|
|
247
|
-
if self.get_project(target_repo_name) is not None:
|
|
248
|
-
print(f"Project {target_repo_name} already exists. Exiting...")
|
|
249
|
-
return
|
|
250
|
-
project = self.create_repository(target_repo_name, provide_owner_access=True, user_id=user_id)
|
|
251
|
-
new_repo_dir = Statics.pwd + Statics.dir_sep + f"{target_repo_name}_new"
|
|
252
|
-
new_repo = GitOperations.setup_repo(repo_dir=f"{new_repo_dir}", repo_url=project.ssh_url_to_repo)
|
|
253
|
-
for item in Path(old_repo.working_tree_dir).rglob('*'):
|
|
254
|
-
if '.git' in item.parts:
|
|
255
|
-
continue
|
|
256
|
-
destination = Path(new_repo.working_tree_dir) / item.relative_to(Path(old_repo.working_tree_dir))
|
|
257
|
-
if item.is_dir():
|
|
258
|
-
destination.mkdir(parents=True, exist_ok=True)
|
|
259
|
-
else:
|
|
260
|
-
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
261
|
-
print(f"Copying {item} to {destination}")
|
|
262
|
-
shutil.copy2(item, destination)
|
|
263
|
-
new_repo.git_push("Initial Commit", push_untracked_files=True)
|
|
264
|
-
FileOp.remove_dir(old_repo.working_tree_dir)
|
|
265
|
-
FileOp.remove_dir(new_repo.working_tree_dir)
|