githubtakeout 0.1.7__tar.gz → 0.1.9__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.7/src/githubtakeout.egg-info → githubtakeout-0.1.9}/PKG-INFO +37 -35
- githubtakeout-0.1.9/README.md +107 -0
- {githubtakeout-0.1.7 → githubtakeout-0.1.9}/pyproject.toml +6 -5
- {githubtakeout-0.1.7 → githubtakeout-0.1.9/src/githubtakeout.egg-info}/PKG-INFO +37 -35
- githubtakeout-0.1.9/src/githubtakeout.egg-info/requires.txt +4 -0
- {githubtakeout-0.1.7 → githubtakeout-0.1.9}/src/githubtakeout.py +76 -52
- githubtakeout-0.1.7/README.md +0 -106
- githubtakeout-0.1.7/src/githubtakeout.egg-info/requires.txt +0 -3
- {githubtakeout-0.1.7 → githubtakeout-0.1.9}/LICENSE +0 -0
- {githubtakeout-0.1.7 → githubtakeout-0.1.9}/setup.cfg +0 -0
- {githubtakeout-0.1.7 → githubtakeout-0.1.9}/src/githubtakeout.egg-info/SOURCES.txt +0 -0
- {githubtakeout-0.1.7 → githubtakeout-0.1.9}/src/githubtakeout.egg-info/dependency_links.txt +0 -0
- {githubtakeout-0.1.7 → githubtakeout-0.1.9}/src/githubtakeout.egg-info/entry_points.txt +0 -0
- {githubtakeout-0.1.7 → githubtakeout-0.1.9}/src/githubtakeout.egg-info/top_level.txt +0 -0
- {githubtakeout-0.1.7 → githubtakeout-0.1.9}/src/progress.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: githubtakeout
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.9
|
|
4
4
|
Summary: Archive public Git Repos and Gists from GitHub
|
|
5
5
|
Author: Corey Goldberg
|
|
6
6
|
Maintainer: Corey Goldberg
|
|
@@ -18,9 +18,10 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
18
18
|
Requires-Python: >=3.12
|
|
19
19
|
Description-Content-Type: text/markdown
|
|
20
20
|
License-File: LICENSE
|
|
21
|
-
Requires-Dist: GitPython==3.1.
|
|
22
|
-
Requires-Dist: PyGithub==2.
|
|
23
|
-
Requires-Dist: rich==14.
|
|
21
|
+
Requires-Dist: GitPython==3.1.45
|
|
22
|
+
Requires-Dist: PyGithub==2.8.1
|
|
23
|
+
Requires-Dist: rich==14.1.0
|
|
24
|
+
Requires-Dist: tenacity==9.1.2
|
|
24
25
|
Dynamic: license-file
|
|
25
26
|
|
|
26
27
|
# githubtakeout
|
|
@@ -29,10 +30,10 @@ Dynamic: license-file
|
|
|
29
30
|
|
|
30
31
|
---
|
|
31
32
|
|
|
32
|
-
- Copyright (c) 2015-2025 [Corey Goldberg]
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
33
|
+
- Copyright (c) 2015-2025 [Corey Goldberg][github-home]
|
|
34
|
+
- Development: [GitHub][github-repo]
|
|
35
|
+
- Download/Install: [PyPI][pypi-githubtakeout]
|
|
36
|
+
- License: [MIT][mit-license]
|
|
36
37
|
|
|
37
38
|
----
|
|
38
39
|
|
|
@@ -57,12 +58,13 @@ as tarballs (`.tar.gz`) using the `--format=tar` option.
|
|
|
57
58
|
- Python 3.12+
|
|
58
59
|
- Git 1.7+
|
|
59
60
|
- Python packages:
|
|
60
|
-
- GitPython
|
|
61
|
-
- PyGithub
|
|
61
|
+
- [GitPython][pypi-gitpython]
|
|
62
|
+
- [PyGithub][pypi-pygithub]
|
|
63
|
+
- [rich][pypi-rich]
|
|
62
64
|
|
|
63
65
|
## Installation:
|
|
64
66
|
|
|
65
|
-
Install from [PyPI]
|
|
67
|
+
Install from [PyPI][pypyi-githubtakeout]:
|
|
66
68
|
|
|
67
69
|
```
|
|
68
70
|
pip install githubtakeout
|
|
@@ -70,14 +72,14 @@ pip install githubtakeout
|
|
|
70
72
|
|
|
71
73
|
## Authentication:
|
|
72
74
|
|
|
73
|
-
By default, `githubtakeout` will only retrieve an account's public repos. To access
|
|
74
|
-
|
|
75
|
+
By default, `githubtakeout` will only retrieve an account's public repos. To access private repos and secret gists,
|
|
76
|
+
you need to authenticate.
|
|
75
77
|
|
|
76
|
-
First, you must create a [personal access token]
|
|
77
|
-
|
|
78
|
+
First, you must create a [personal access token][github-pat] on Github (either a fine-grained or classic personal
|
|
79
|
+
access token). Once you have a token, you can set the `GITHUB_TOKEN` environment variable:
|
|
78
80
|
|
|
79
81
|
```
|
|
80
|
-
$ export GITHUB_TOKEN=<
|
|
82
|
+
$ export GITHUB_TOKEN=<access token>
|
|
81
83
|
```
|
|
82
84
|
|
|
83
85
|
If you prefer to be prompted for your token each time you run the program, use the `--token` argument.
|
|
@@ -85,22 +87,21 @@ If you prefer to be prompted for your token each time you run the program, use t
|
|
|
85
87
|
### CLI Options:
|
|
86
88
|
|
|
87
89
|
```
|
|
88
|
-
usage: githubtakeout [-h] [--dir DIR] [--format
|
|
90
|
+
usage: githubtakeout [-h] [--dir DIR] [--format {tar,zip}] [--gists] [--history] [--list] [--token] username
|
|
89
91
|
|
|
90
92
|
positional arguments:
|
|
91
|
-
username
|
|
93
|
+
username github username
|
|
92
94
|
|
|
93
95
|
options:
|
|
94
|
-
-h, --help
|
|
95
|
-
--dir DIR
|
|
96
|
-
--format
|
|
97
|
-
--gists
|
|
98
|
-
--history
|
|
99
|
-
--list
|
|
100
|
-
--token
|
|
96
|
+
-h, --help show this help message and exit
|
|
97
|
+
--dir DIR output directory (default: ./)
|
|
98
|
+
--format {tar,zip} archive format (default: zip)
|
|
99
|
+
--gists include gists
|
|
100
|
+
--history include commit history and branches (.git directory)
|
|
101
|
+
--list list repos only
|
|
102
|
+
--token prompt for auth token
|
|
101
103
|
```
|
|
102
104
|
|
|
103
|
-
|
|
104
105
|
## Usage Examples:
|
|
105
106
|
|
|
106
107
|
### Install from PyPI with pipx, Run:
|
|
@@ -110,15 +111,6 @@ pipx install githubtakeout
|
|
|
110
111
|
githubtakeout <github username>
|
|
111
112
|
```
|
|
112
113
|
|
|
113
|
-
### Create/Activate Virtual Environment, Install from PyPI, Run:
|
|
114
|
-
|
|
115
|
-
```
|
|
116
|
-
python3 -m venv venv
|
|
117
|
-
source venv/bin/activate
|
|
118
|
-
pip install githubtakeout
|
|
119
|
-
githubtakeout <github username>
|
|
120
|
-
```
|
|
121
|
-
|
|
122
114
|
### Clone Repo, Create/Activate Virtual Environment, Install from Source, Run:
|
|
123
115
|
|
|
124
116
|
```
|
|
@@ -129,3 +121,13 @@ source venv/bin/activate
|
|
|
129
121
|
pip install .
|
|
130
122
|
githubtakeout <github username>
|
|
131
123
|
```
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
[github-home]: https://github.com/cgoldberg
|
|
127
|
+
[github-repo]: https://github.com/cgoldberg/sudokubot
|
|
128
|
+
[github-pat]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
|
|
129
|
+
[pypi-githubtakeout]: https://pypi.org/project/githubtakeout
|
|
130
|
+
[pypi-gitpython]: https://pypi.org/project/GitPython
|
|
131
|
+
[pypi-pygithub]: https://pypi.org/project/PyGithub
|
|
132
|
+
[pypi-rich]: https://pypi.org/project/rich
|
|
133
|
+
[mit-license]: https://raw.githubusercontent.com/cgoldberg/githubtakeout/refs/heads/master/LICENSE
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# githubtakeout
|
|
2
|
+
|
|
3
|
+
## Archive Git Repos and Gists from GitHub
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
- Copyright (c) 2015-2025 [Corey Goldberg][github-home]
|
|
8
|
+
- Development: [GitHub][github-repo]
|
|
9
|
+
- Download/Install: [PyPI][pypi-githubtakeout]
|
|
10
|
+
- License: [MIT][mit-license]
|
|
11
|
+
|
|
12
|
+
----
|
|
13
|
+
|
|
14
|
+
## About:
|
|
15
|
+
|
|
16
|
+
`githubtakeout` is a data export tool for archiving Git repositories hosted on GitHub.
|
|
17
|
+
It clones a user's repos and creates an archive of each.
|
|
18
|
+
|
|
19
|
+
It supports public/private repos and public/secret gists. By default, it doesn't save
|
|
20
|
+
commit history or branches (`.git` directory), or Gist repositories (both can be enabled
|
|
21
|
+
with command line options).
|
|
22
|
+
|
|
23
|
+
When you run the program, archives of your repos will be saved in a directory named
|
|
24
|
+
`backups` inside your current working directory, unless a different location is specified
|
|
25
|
+
using the `--dir` option.
|
|
26
|
+
|
|
27
|
+
Archives are saved in compressed zip format (`.zip`) by default, but can also be saved
|
|
28
|
+
as tarballs (`.tar.gz`) using the `--format=tar` option.
|
|
29
|
+
|
|
30
|
+
## Requirements:
|
|
31
|
+
|
|
32
|
+
- Python 3.12+
|
|
33
|
+
- Git 1.7+
|
|
34
|
+
- Python packages:
|
|
35
|
+
- [GitPython][pypi-gitpython]
|
|
36
|
+
- [PyGithub][pypi-pygithub]
|
|
37
|
+
- [rich][pypi-rich]
|
|
38
|
+
|
|
39
|
+
## Installation:
|
|
40
|
+
|
|
41
|
+
Install from [PyPI][pypyi-githubtakeout]:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
pip install githubtakeout
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Authentication:
|
|
48
|
+
|
|
49
|
+
By default, `githubtakeout` will only retrieve an account's public repos. To access private repos and secret gists,
|
|
50
|
+
you need to authenticate.
|
|
51
|
+
|
|
52
|
+
First, you must create a [personal access token][github-pat] on Github (either a fine-grained or classic personal
|
|
53
|
+
access token). Once you have a token, you can set the `GITHUB_TOKEN` environment variable:
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
$ export GITHUB_TOKEN=<access token>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If you prefer to be prompted for your token each time you run the program, use the `--token` argument.
|
|
60
|
+
|
|
61
|
+
### CLI Options:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
usage: githubtakeout [-h] [--dir DIR] [--format {tar,zip}] [--gists] [--history] [--list] [--token] username
|
|
65
|
+
|
|
66
|
+
positional arguments:
|
|
67
|
+
username github username
|
|
68
|
+
|
|
69
|
+
options:
|
|
70
|
+
-h, --help show this help message and exit
|
|
71
|
+
--dir DIR output directory (default: ./)
|
|
72
|
+
--format {tar,zip} archive format (default: zip)
|
|
73
|
+
--gists include gists
|
|
74
|
+
--history include commit history and branches (.git directory)
|
|
75
|
+
--list list repos only
|
|
76
|
+
--token prompt for auth token
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Usage Examples:
|
|
80
|
+
|
|
81
|
+
### Install from PyPI with pipx, Run:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
pipx install githubtakeout
|
|
85
|
+
githubtakeout <github username>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Clone Repo, Create/Activate Virtual Environment, Install from Source, Run:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
git clone git@github.com:cgoldberg/githubtakeout.git
|
|
92
|
+
cd ./githubtakeout
|
|
93
|
+
python3 -m venv venv
|
|
94
|
+
source venv/bin/activate
|
|
95
|
+
pip install .
|
|
96
|
+
githubtakeout <github username>
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
[github-home]: https://github.com/cgoldberg
|
|
101
|
+
[github-repo]: https://github.com/cgoldberg/sudokubot
|
|
102
|
+
[github-pat]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
|
|
103
|
+
[pypi-githubtakeout]: https://pypi.org/project/githubtakeout
|
|
104
|
+
[pypi-gitpython]: https://pypi.org/project/GitPython
|
|
105
|
+
[pypi-pygithub]: https://pypi.org/project/PyGithub
|
|
106
|
+
[pypi-rich]: https://pypi.org/project/rich
|
|
107
|
+
[mit-license]: https://raw.githubusercontent.com/cgoldberg/githubtakeout/refs/heads/master/LICENSE
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "githubtakeout"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.9"
|
|
8
8
|
description = "Archive public Git Repos and Gists from GitHub"
|
|
9
9
|
license = "MIT"
|
|
10
10
|
license-files = ["LICENSE"]
|
|
@@ -22,9 +22,10 @@ classifiers = [
|
|
|
22
22
|
"Programming Language :: Python :: 3.13",
|
|
23
23
|
]
|
|
24
24
|
dependencies = [
|
|
25
|
-
"GitPython==3.1.
|
|
26
|
-
"PyGithub==2.
|
|
27
|
-
"rich==14.
|
|
25
|
+
"GitPython==3.1.45",
|
|
26
|
+
"PyGithub==2.8.1",
|
|
27
|
+
"rich==14.1.0",
|
|
28
|
+
"tenacity==9.1.2",
|
|
28
29
|
]
|
|
29
30
|
|
|
30
31
|
[project.scripts]
|
|
@@ -40,7 +41,7 @@ package-dir = {"" = "src"}
|
|
|
40
41
|
|
|
41
42
|
[tool.black]
|
|
42
43
|
line-length = 88
|
|
43
|
-
target-version = ["py312"]
|
|
44
|
+
target-version = ["py39", "py310", "py311", "py312", "py313"]
|
|
44
45
|
|
|
45
46
|
[tool.ruff]
|
|
46
47
|
line-length = 88
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: githubtakeout
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.9
|
|
4
4
|
Summary: Archive public Git Repos and Gists from GitHub
|
|
5
5
|
Author: Corey Goldberg
|
|
6
6
|
Maintainer: Corey Goldberg
|
|
@@ -18,9 +18,10 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
18
18
|
Requires-Python: >=3.12
|
|
19
19
|
Description-Content-Type: text/markdown
|
|
20
20
|
License-File: LICENSE
|
|
21
|
-
Requires-Dist: GitPython==3.1.
|
|
22
|
-
Requires-Dist: PyGithub==2.
|
|
23
|
-
Requires-Dist: rich==14.
|
|
21
|
+
Requires-Dist: GitPython==3.1.45
|
|
22
|
+
Requires-Dist: PyGithub==2.8.1
|
|
23
|
+
Requires-Dist: rich==14.1.0
|
|
24
|
+
Requires-Dist: tenacity==9.1.2
|
|
24
25
|
Dynamic: license-file
|
|
25
26
|
|
|
26
27
|
# githubtakeout
|
|
@@ -29,10 +30,10 @@ Dynamic: license-file
|
|
|
29
30
|
|
|
30
31
|
---
|
|
31
32
|
|
|
32
|
-
- Copyright (c) 2015-2025 [Corey Goldberg]
|
|
33
|
-
-
|
|
34
|
-
-
|
|
35
|
-
-
|
|
33
|
+
- Copyright (c) 2015-2025 [Corey Goldberg][github-home]
|
|
34
|
+
- Development: [GitHub][github-repo]
|
|
35
|
+
- Download/Install: [PyPI][pypi-githubtakeout]
|
|
36
|
+
- License: [MIT][mit-license]
|
|
36
37
|
|
|
37
38
|
----
|
|
38
39
|
|
|
@@ -57,12 +58,13 @@ as tarballs (`.tar.gz`) using the `--format=tar` option.
|
|
|
57
58
|
- Python 3.12+
|
|
58
59
|
- Git 1.7+
|
|
59
60
|
- Python packages:
|
|
60
|
-
- GitPython
|
|
61
|
-
- PyGithub
|
|
61
|
+
- [GitPython][pypi-gitpython]
|
|
62
|
+
- [PyGithub][pypi-pygithub]
|
|
63
|
+
- [rich][pypi-rich]
|
|
62
64
|
|
|
63
65
|
## Installation:
|
|
64
66
|
|
|
65
|
-
Install from [PyPI]
|
|
67
|
+
Install from [PyPI][pypyi-githubtakeout]:
|
|
66
68
|
|
|
67
69
|
```
|
|
68
70
|
pip install githubtakeout
|
|
@@ -70,14 +72,14 @@ pip install githubtakeout
|
|
|
70
72
|
|
|
71
73
|
## Authentication:
|
|
72
74
|
|
|
73
|
-
By default, `githubtakeout` will only retrieve an account's public repos. To access
|
|
74
|
-
|
|
75
|
+
By default, `githubtakeout` will only retrieve an account's public repos. To access private repos and secret gists,
|
|
76
|
+
you need to authenticate.
|
|
75
77
|
|
|
76
|
-
First, you must create a [personal access token]
|
|
77
|
-
|
|
78
|
+
First, you must create a [personal access token][github-pat] on Github (either a fine-grained or classic personal
|
|
79
|
+
access token). Once you have a token, you can set the `GITHUB_TOKEN` environment variable:
|
|
78
80
|
|
|
79
81
|
```
|
|
80
|
-
$ export GITHUB_TOKEN=<
|
|
82
|
+
$ export GITHUB_TOKEN=<access token>
|
|
81
83
|
```
|
|
82
84
|
|
|
83
85
|
If you prefer to be prompted for your token each time you run the program, use the `--token` argument.
|
|
@@ -85,22 +87,21 @@ If you prefer to be prompted for your token each time you run the program, use t
|
|
|
85
87
|
### CLI Options:
|
|
86
88
|
|
|
87
89
|
```
|
|
88
|
-
usage: githubtakeout [-h] [--dir DIR] [--format
|
|
90
|
+
usage: githubtakeout [-h] [--dir DIR] [--format {tar,zip}] [--gists] [--history] [--list] [--token] username
|
|
89
91
|
|
|
90
92
|
positional arguments:
|
|
91
|
-
username
|
|
93
|
+
username github username
|
|
92
94
|
|
|
93
95
|
options:
|
|
94
|
-
-h, --help
|
|
95
|
-
--dir DIR
|
|
96
|
-
--format
|
|
97
|
-
--gists
|
|
98
|
-
--history
|
|
99
|
-
--list
|
|
100
|
-
--token
|
|
96
|
+
-h, --help show this help message and exit
|
|
97
|
+
--dir DIR output directory (default: ./)
|
|
98
|
+
--format {tar,zip} archive format (default: zip)
|
|
99
|
+
--gists include gists
|
|
100
|
+
--history include commit history and branches (.git directory)
|
|
101
|
+
--list list repos only
|
|
102
|
+
--token prompt for auth token
|
|
101
103
|
```
|
|
102
104
|
|
|
103
|
-
|
|
104
105
|
## Usage Examples:
|
|
105
106
|
|
|
106
107
|
### Install from PyPI with pipx, Run:
|
|
@@ -110,15 +111,6 @@ pipx install githubtakeout
|
|
|
110
111
|
githubtakeout <github username>
|
|
111
112
|
```
|
|
112
113
|
|
|
113
|
-
### Create/Activate Virtual Environment, Install from PyPI, Run:
|
|
114
|
-
|
|
115
|
-
```
|
|
116
|
-
python3 -m venv venv
|
|
117
|
-
source venv/bin/activate
|
|
118
|
-
pip install githubtakeout
|
|
119
|
-
githubtakeout <github username>
|
|
120
|
-
```
|
|
121
|
-
|
|
122
114
|
### Clone Repo, Create/Activate Virtual Environment, Install from Source, Run:
|
|
123
115
|
|
|
124
116
|
```
|
|
@@ -129,3 +121,13 @@ source venv/bin/activate
|
|
|
129
121
|
pip install .
|
|
130
122
|
githubtakeout <github username>
|
|
131
123
|
```
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
[github-home]: https://github.com/cgoldberg
|
|
127
|
+
[github-repo]: https://github.com/cgoldberg/sudokubot
|
|
128
|
+
[github-pat]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
|
|
129
|
+
[pypi-githubtakeout]: https://pypi.org/project/githubtakeout
|
|
130
|
+
[pypi-gitpython]: https://pypi.org/project/GitPython
|
|
131
|
+
[pypi-pygithub]: https://pypi.org/project/PyGithub
|
|
132
|
+
[pypi-rich]: https://pypi.org/project/rich
|
|
133
|
+
[mit-license]: https://raw.githubusercontent.com/cgoldberg/githubtakeout/refs/heads/master/LICENSE
|
|
@@ -19,9 +19,12 @@ from timeit import default_timer
|
|
|
19
19
|
|
|
20
20
|
import git
|
|
21
21
|
import github
|
|
22
|
+
from tenacity import retry, stop_after_attempt, wait_fixed
|
|
22
23
|
|
|
23
24
|
from progress import GitProgress
|
|
24
25
|
|
|
26
|
+
ARCHIVE_FORMATS = ("tar", "zip")
|
|
27
|
+
|
|
25
28
|
logging.basicConfig(level=logging.INFO, format="%(message)s")
|
|
26
29
|
logger = logging.getLogger(__name__)
|
|
27
30
|
|
|
@@ -47,53 +50,6 @@ def add_creds(url, username, token):
|
|
|
47
50
|
return new_url
|
|
48
51
|
|
|
49
52
|
|
|
50
|
-
def archive(local_repo_dir, archive_format="zip", is_gist=False):
|
|
51
|
-
if archive_format not in ("tar", "zip"):
|
|
52
|
-
raise ValueError(f"{archive_format} is not a valid archive format")
|
|
53
|
-
base_name = os.path.basename(local_repo_dir)
|
|
54
|
-
extension = "tar.gz" if archive_format == "tar" else archive_format
|
|
55
|
-
archive_name = f"{base_name}.{extension}"
|
|
56
|
-
if is_gist:
|
|
57
|
-
archive_name = f"gist-{archive_name}"
|
|
58
|
-
parent_dir = os.path.dirname(local_repo_dir)
|
|
59
|
-
archive_path = os.path.join(parent_dir, archive_name)
|
|
60
|
-
logger.info(f"creating archive: {archive_path}")
|
|
61
|
-
if archive_format == "tar":
|
|
62
|
-
with tarfile.open(archive_path, "w:gz") as tar_archive:
|
|
63
|
-
tar_archive.add(local_repo_dir, arcname=base_name)
|
|
64
|
-
elif archive_format == "zip":
|
|
65
|
-
with zipfile.ZipFile(archive_path, "w", zipfile.ZIP_DEFLATED) as zip_archive:
|
|
66
|
-
repo_path = Path(local_repo_dir)
|
|
67
|
-
for entry in repo_path.rglob("*"):
|
|
68
|
-
path = os.path.join(base_name, entry.relative_to(repo_path))
|
|
69
|
-
zip_archive.write(entry, arcname=path)
|
|
70
|
-
return archive_path
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def clone(repo_url, local_repo_dir, include_history):
|
|
74
|
-
try:
|
|
75
|
-
if include_history:
|
|
76
|
-
# full clone
|
|
77
|
-
repo = git.Repo.clone_from(
|
|
78
|
-
url=repo_url, to_path=local_repo_dir, progress=GitProgress()
|
|
79
|
-
)
|
|
80
|
-
else:
|
|
81
|
-
# shallow clone (no commit history or branches)
|
|
82
|
-
repo = git.Repo.clone_from(
|
|
83
|
-
url=repo_url, to_path=local_repo_dir, depth=1, progress=GitProgress()
|
|
84
|
-
)
|
|
85
|
-
except git.GitCommandError as e:
|
|
86
|
-
logger.error(e)
|
|
87
|
-
sys.exit("error: failed cloning repo")
|
|
88
|
-
finally:
|
|
89
|
-
try:
|
|
90
|
-
# release resources
|
|
91
|
-
repo.close()
|
|
92
|
-
except UnboundLocalError:
|
|
93
|
-
# this occurs if we catch a signal while cloning
|
|
94
|
-
pass
|
|
95
|
-
|
|
96
|
-
|
|
97
53
|
def clone_and_archive_repo(
|
|
98
54
|
repo_url, local_repo_dir, archive_format, include_history, is_gist=False
|
|
99
55
|
):
|
|
@@ -140,6 +96,65 @@ def clone_and_archive_repo(
|
|
|
140
96
|
logger.info(f"successfully backed up '{base_name}' repo in {elapsed:.3f} secs\n")
|
|
141
97
|
|
|
142
98
|
|
|
99
|
+
def archive(local_repo_dir, archive_format="zip", is_gist=False):
|
|
100
|
+
if archive_format not in ARCHIVE_FORMATS:
|
|
101
|
+
raise ValueError(f"{archive_format} is not a valid archive format")
|
|
102
|
+
base_name = os.path.basename(local_repo_dir)
|
|
103
|
+
extension = "tar.gz" if archive_format == "tar" else archive_format
|
|
104
|
+
archive_name = f"{base_name}.{extension}"
|
|
105
|
+
if is_gist:
|
|
106
|
+
archive_name = f"gist-{archive_name}"
|
|
107
|
+
parent_dir = os.path.dirname(local_repo_dir)
|
|
108
|
+
archive_path = os.path.join(parent_dir, archive_name)
|
|
109
|
+
logger.info(f"creating archive: {archive_path}")
|
|
110
|
+
if archive_format == "tar":
|
|
111
|
+
with tarfile.open(archive_path, "w:gz") as tar_archive:
|
|
112
|
+
tar_archive.add(local_repo_dir, arcname=base_name)
|
|
113
|
+
elif archive_format == "zip":
|
|
114
|
+
with zipfile.ZipFile(archive_path, "w", zipfile.ZIP_DEFLATED) as zip_archive:
|
|
115
|
+
repo_path = Path(local_repo_dir)
|
|
116
|
+
for entry in repo_path.rglob("*"):
|
|
117
|
+
path = os.path.join(base_name, entry.relative_to(repo_path))
|
|
118
|
+
zip_archive.write(entry, arcname=path)
|
|
119
|
+
return archive_path
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@retry(stop=stop_after_attempt(5), wait=wait_fixed(2))
|
|
123
|
+
def clone(repo_url, local_repo_dir, include_history):
|
|
124
|
+
try:
|
|
125
|
+
if include_history:
|
|
126
|
+
# full clone
|
|
127
|
+
repo = git.Repo.clone_from(
|
|
128
|
+
url=repo_url,
|
|
129
|
+
to_path=local_repo_dir,
|
|
130
|
+
progress=GitProgress(),
|
|
131
|
+
)
|
|
132
|
+
else:
|
|
133
|
+
# shallow clone (no commit history or branches)
|
|
134
|
+
repo = git.Repo.clone_from(
|
|
135
|
+
url=repo_url,
|
|
136
|
+
to_path=local_repo_dir,
|
|
137
|
+
multi_options=["--depth=1"],
|
|
138
|
+
progress=GitProgress(),
|
|
139
|
+
)
|
|
140
|
+
except git.GitCommandError as e:
|
|
141
|
+
logger.error(e)
|
|
142
|
+
sys.exit("error: failed cloning repo")
|
|
143
|
+
finally:
|
|
144
|
+
try:
|
|
145
|
+
# release resources
|
|
146
|
+
repo.close()
|
|
147
|
+
except UnboundLocalError:
|
|
148
|
+
# this occurs if we catch a signal while cloning
|
|
149
|
+
pass
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@retry(stop=stop_after_attempt(5), wait=wait_fixed(2))
|
|
153
|
+
def count_repos(repos):
|
|
154
|
+
return repos.totalCount
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@retry(stop=stop_after_attempt(5), wait=wait_fixed(2))
|
|
143
158
|
def get_user(username, prompt_token):
|
|
144
159
|
if prompt_token:
|
|
145
160
|
token = getpass.getpass("Token:")
|
|
@@ -170,7 +185,7 @@ def get_user(username, prompt_token):
|
|
|
170
185
|
repos = user.get_repos(affiliation="owner")
|
|
171
186
|
try:
|
|
172
187
|
# this just makes an API request so we can exit if unauthorized
|
|
173
|
-
_ = repos
|
|
188
|
+
_ = count_repos(repos)
|
|
174
189
|
except github.GithubException as e:
|
|
175
190
|
if e.data["status"] == "401":
|
|
176
191
|
sys.exit(f"error: invalid auth token for user '{username}'")
|
|
@@ -191,7 +206,7 @@ def run(
|
|
|
191
206
|
):
|
|
192
207
|
working_dir = os.path.join(base_dir, "backups")
|
|
193
208
|
user, repos, gists, token = get_user(username, prompt_token)
|
|
194
|
-
num_repos = repos
|
|
209
|
+
num_repos = count_repos(repos)
|
|
195
210
|
if not list_only:
|
|
196
211
|
logger.info(f"creating archives in: {working_dir}\n")
|
|
197
212
|
logger.info(f"found {num_repos} repos for user '{username}'\n")
|
|
@@ -203,7 +218,7 @@ def run(
|
|
|
203
218
|
else:
|
|
204
219
|
clone_and_archive_repo(url, local_repo_dir, archive_format, include_history)
|
|
205
220
|
if include_gists:
|
|
206
|
-
num_gists = gists
|
|
221
|
+
num_gists = count_repos(gists)
|
|
207
222
|
logger.info("")
|
|
208
223
|
logger.info(f"found {num_gists} gists for user '{username}'\n")
|
|
209
224
|
for gist in gists:
|
|
@@ -222,8 +237,17 @@ def main():
|
|
|
222
237
|
sys.exit("sorry, this program requires Python 3.12+")
|
|
223
238
|
parser = argparse.ArgumentParser()
|
|
224
239
|
parser.add_argument("username", help="github username")
|
|
225
|
-
parser.add_argument(
|
|
226
|
-
|
|
240
|
+
parser.add_argument(
|
|
241
|
+
"--dir",
|
|
242
|
+
default=os.getcwd(),
|
|
243
|
+
help="output directory (default: ./)",
|
|
244
|
+
)
|
|
245
|
+
parser.add_argument(
|
|
246
|
+
"--format",
|
|
247
|
+
choices=ARCHIVE_FORMATS,
|
|
248
|
+
default="zip",
|
|
249
|
+
help="archive format (default: %(default)s)",
|
|
250
|
+
)
|
|
227
251
|
parser.add_argument(
|
|
228
252
|
"--gists", action="store_true", default=False, help="include gists"
|
|
229
253
|
)
|
githubtakeout-0.1.7/README.md
DELETED
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
# githubtakeout
|
|
2
|
-
|
|
3
|
-
## Archive Git Repos and Gists from GitHub
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
- Copyright (c) 2015-2025 [Corey Goldberg](https://github.com/cgoldberg)
|
|
8
|
-
- License: [MIT](https://raw.githubusercontent.com/cgoldberg/githubtakeout/refs/heads/master/LICENSE)
|
|
9
|
-
- Development: [GitHub](https://github.com/cgoldberg/githubtakeout)
|
|
10
|
-
- Download/Install: [PyPI](https://pypi.org/project/githubtakeout)
|
|
11
|
-
|
|
12
|
-
----
|
|
13
|
-
|
|
14
|
-
## About:
|
|
15
|
-
|
|
16
|
-
`githubtakeout` is a data export tool for archiving Git repositories hosted on GitHub.
|
|
17
|
-
It clones a user's repos and creates an archive of each.
|
|
18
|
-
|
|
19
|
-
It supports public/private repos and public/secret gists. By default, it doesn't save
|
|
20
|
-
commit history or branches (`.git` directory), or Gist repositories (both can be enabled
|
|
21
|
-
with command line options).
|
|
22
|
-
|
|
23
|
-
When you run the program, archives of your repos will be saved in a directory named
|
|
24
|
-
`backups` inside your current working directory, unless a different location is specified
|
|
25
|
-
using the `--dir` option.
|
|
26
|
-
|
|
27
|
-
Archives are saved in compressed zip format (`.zip`) by default, but can also be saved
|
|
28
|
-
as tarballs (`.tar.gz`) using the `--format=tar` option.
|
|
29
|
-
|
|
30
|
-
## Requirements:
|
|
31
|
-
|
|
32
|
-
- Python 3.12+
|
|
33
|
-
- Git 1.7+
|
|
34
|
-
- Python packages:
|
|
35
|
-
- GitPython
|
|
36
|
-
- PyGithub
|
|
37
|
-
|
|
38
|
-
## Installation:
|
|
39
|
-
|
|
40
|
-
Install from [PyPI](https://pypi.org/project/githubtakeout):
|
|
41
|
-
|
|
42
|
-
```
|
|
43
|
-
pip install githubtakeout
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Authentication:
|
|
47
|
-
|
|
48
|
-
By default, `githubtakeout` will only retrieve an account's public repos. To access
|
|
49
|
-
private repos and secret gists, you need to authenticate.
|
|
50
|
-
|
|
51
|
-
First, you must create a [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens)
|
|
52
|
-
on Github (either a fine-grained or classic personal access token). Once you have a token, you can set the `GITHUB_TOKEN` environment variable:
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
$ export GITHUB_TOKEN=<auth token created on GitHub>
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
If you prefer to be prompted for your token each time you run the program, use the `--token` argument.
|
|
59
|
-
|
|
60
|
-
### CLI Options:
|
|
61
|
-
|
|
62
|
-
```
|
|
63
|
-
usage: githubtakeout [-h] [--dir DIR] [--format FORMAT] [--gists] [--history] [--list] [--token] username
|
|
64
|
-
|
|
65
|
-
positional arguments:
|
|
66
|
-
username GitHub username
|
|
67
|
-
|
|
68
|
-
options:
|
|
69
|
-
-h, --help show this help message and exit
|
|
70
|
-
--dir DIR output directory
|
|
71
|
-
--format FORMAT archive format (tar, zip)
|
|
72
|
-
--gists include gists
|
|
73
|
-
--history include commit history and branches (.git directory)
|
|
74
|
-
--list list repos only
|
|
75
|
-
--token prompt for auth toke
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
## Usage Examples:
|
|
80
|
-
|
|
81
|
-
### Install from PyPI with pipx, Run:
|
|
82
|
-
|
|
83
|
-
```
|
|
84
|
-
pipx install githubtakeout
|
|
85
|
-
githubtakeout <github username>
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Create/Activate Virtual Environment, Install from PyPI, Run:
|
|
89
|
-
|
|
90
|
-
```
|
|
91
|
-
python3 -m venv venv
|
|
92
|
-
source venv/bin/activate
|
|
93
|
-
pip install githubtakeout
|
|
94
|
-
githubtakeout <github username>
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### Clone Repo, Create/Activate Virtual Environment, Install from Source, Run:
|
|
98
|
-
|
|
99
|
-
```
|
|
100
|
-
git clone git@github.com:cgoldberg/githubtakeout.git
|
|
101
|
-
cd ./githubtakeout
|
|
102
|
-
python3 -m venv venv
|
|
103
|
-
source venv/bin/activate
|
|
104
|
-
pip install .
|
|
105
|
-
githubtakeout <github username>
|
|
106
|
-
```
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|