githubtakeout 0.1.2__tar.gz → 0.1.4__tar.gz
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.
- {githubtakeout-0.1.2 → githubtakeout-0.1.4}/PKG-INFO +1 -1
- {githubtakeout-0.1.2 → githubtakeout-0.1.4}/githubtakeout.egg-info/PKG-INFO +1 -1
- {githubtakeout-0.1.2 → githubtakeout-0.1.4}/githubtakeout.py +61 -32
- {githubtakeout-0.1.2 → githubtakeout-0.1.4}/pyproject.toml +1 -1
- {githubtakeout-0.1.2 → githubtakeout-0.1.4}/LICENSE +0 -0
- {githubtakeout-0.1.2 → githubtakeout-0.1.4}/README.md +0 -0
- {githubtakeout-0.1.2 → githubtakeout-0.1.4}/githubtakeout.egg-info/SOURCES.txt +0 -0
- {githubtakeout-0.1.2 → githubtakeout-0.1.4}/githubtakeout.egg-info/dependency_links.txt +0 -0
- {githubtakeout-0.1.2 → githubtakeout-0.1.4}/githubtakeout.egg-info/entry_points.txt +0 -0
- {githubtakeout-0.1.2 → githubtakeout-0.1.4}/githubtakeout.egg-info/requires.txt +0 -0
- {githubtakeout-0.1.2 → githubtakeout-0.1.4}/githubtakeout.egg-info/top_level.txt +0 -0
- {githubtakeout-0.1.2 → githubtakeout-0.1.4}/setup.cfg +0 -0
|
@@ -56,37 +56,63 @@ def archive(local_repo_dir, archive_format='zip', is_gist=False):
|
|
|
56
56
|
return archive_path
|
|
57
57
|
|
|
58
58
|
|
|
59
|
+
def clone(repo_url, local_repo_dir, include_history):
|
|
60
|
+
try:
|
|
61
|
+
if include_history:
|
|
62
|
+
# full clone
|
|
63
|
+
repo = git.Repo.clone_from(repo_url, local_repo_dir)
|
|
64
|
+
else:
|
|
65
|
+
# shallow clone (no commit history or branches)
|
|
66
|
+
repo = git.Repo.clone_from(repo_url, local_repo_dir, multi_options=['--depth=1'])
|
|
67
|
+
except git.GitCommandError as e:
|
|
68
|
+
logger.error(e)
|
|
69
|
+
sys.exit('Error: failed cloning repo')
|
|
70
|
+
finally:
|
|
71
|
+
try:
|
|
72
|
+
# release resources
|
|
73
|
+
repo.close()
|
|
74
|
+
except UnboundLocalError:
|
|
75
|
+
# this occurs if we catch a signal while cloning
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
59
80
|
def clone_and_archive_repo(repo_url, local_repo_dir, archive_format, include_history, is_gist=False):
|
|
60
81
|
def remove_readonly(func, path, _):
|
|
61
|
-
#
|
|
82
|
+
# This is necessary so rmtree() doesn't fail if there are any readonly
|
|
83
|
+
# dirs/files when trying to delete. This seems to happen after cloning on
|
|
84
|
+
# Windows. When any error occurs during deletion, we change the permissions
|
|
85
|
+
# and and reattempt removal.
|
|
86
|
+
#
|
|
87
|
+
# give read permissions
|
|
88
|
+
os.chmod(path, stat.S_IREAD)
|
|
89
|
+
# give write permissions
|
|
62
90
|
os.chmod(path, stat.S_IWRITE)
|
|
91
|
+
# try again
|
|
63
92
|
func(path)
|
|
64
93
|
try:
|
|
94
|
+
# delete repo if it already exists
|
|
65
95
|
shutil.rmtree(local_repo_dir, onexc=remove_readonly)
|
|
66
96
|
except FileNotFoundError:
|
|
67
97
|
pass
|
|
68
|
-
|
|
69
|
-
logger.info(f'cloning repo: {
|
|
98
|
+
repo_name = urllib.parse.urlparse(repo_url).path.lstrip('/')
|
|
99
|
+
logger.info(f'cloning repo: {repo_name} to {local_repo_dir}')
|
|
70
100
|
start = default_timer()
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
except FileNotFoundError:
|
|
80
|
-
pass
|
|
81
|
-
except git.GitCommandError as e:
|
|
82
|
-
logger.error(e)
|
|
83
|
-
return
|
|
101
|
+
clone(repo_url, local_repo_dir, include_history)
|
|
102
|
+
if not include_history:
|
|
103
|
+
# delete the .git directory if we are not saving history
|
|
104
|
+
try:
|
|
105
|
+
git_dir = os.path.join(local_repo_dir, '.git')
|
|
106
|
+
shutil.rmtree(git_dir, onexc=remove_readonly)
|
|
107
|
+
except FileNotFoundError:
|
|
108
|
+
pass
|
|
84
109
|
archive_path = archive(local_repo_dir, archive_format, is_gist)
|
|
85
110
|
size_kb = os.path.getsize(archive_path) / 1024
|
|
86
111
|
logger.info(f'archive size: {size_kb:.2f} KB')
|
|
87
112
|
logger.info('deleting repo')
|
|
88
113
|
try:
|
|
89
|
-
|
|
114
|
+
# delete repo after archive is created
|
|
115
|
+
shutil.rmtree(local_repo_dir, onexc=remove_readonly)
|
|
90
116
|
except FileNotFoundError:
|
|
91
117
|
pass
|
|
92
118
|
elapsed = default_timer() - start
|
|
@@ -174,11 +200,11 @@ def run(username, base_dir, archive_format, include_gists, include_history, list
|
|
|
174
200
|
|
|
175
201
|
def main():
|
|
176
202
|
if sys.version_info < (3, 12):
|
|
177
|
-
sys.exit('
|
|
203
|
+
sys.exit('sorry, this program requires Python 3.12+')
|
|
178
204
|
parser = argparse.ArgumentParser()
|
|
179
205
|
parser.add_argument(
|
|
180
206
|
'username',
|
|
181
|
-
help='
|
|
207
|
+
help='github username'
|
|
182
208
|
)
|
|
183
209
|
parser.add_argument(
|
|
184
210
|
'--dir',
|
|
@@ -192,38 +218,41 @@ def main():
|
|
|
192
218
|
)
|
|
193
219
|
parser.add_argument(
|
|
194
220
|
'--gists',
|
|
195
|
-
default=False,
|
|
196
221
|
action='store_true',
|
|
222
|
+
default=False,
|
|
197
223
|
help='include gists'
|
|
198
224
|
)
|
|
199
225
|
parser.add_argument(
|
|
200
226
|
'--history',
|
|
201
|
-
default=False,
|
|
202
227
|
action='store_true',
|
|
228
|
+
default=False,
|
|
203
229
|
help='include commit history and branches (.git directory)'
|
|
204
230
|
)
|
|
205
231
|
parser.add_argument(
|
|
206
232
|
'--list',
|
|
207
|
-
default=False,
|
|
208
233
|
action='store_true',
|
|
234
|
+
default=False,
|
|
209
235
|
help='list repos only'
|
|
210
236
|
)
|
|
211
237
|
parser.add_argument(
|
|
212
238
|
'--token',
|
|
213
|
-
default=False,
|
|
214
239
|
action='store_true',
|
|
240
|
+
default=False,
|
|
215
241
|
help='prompt for auth token'
|
|
216
242
|
)
|
|
217
243
|
args = parser.parse_args()
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
244
|
+
try:
|
|
245
|
+
run(
|
|
246
|
+
username=args.username,
|
|
247
|
+
base_dir=args.dir,
|
|
248
|
+
archive_format=args.format,
|
|
249
|
+
include_gists=args.gists,
|
|
250
|
+
include_history=args.history,
|
|
251
|
+
list_only=args.list,
|
|
252
|
+
prompt_token=args.token
|
|
253
|
+
)
|
|
254
|
+
except KeyboardInterrupt:
|
|
255
|
+
sys.exit('\nexiting program ...')
|
|
227
256
|
|
|
228
257
|
|
|
229
258
|
if __name__ == '__main__':
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|