githubtakeout 0.1.10__tar.gz → 0.1.12__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.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: githubtakeout
3
- Version: 0.1.10
4
- Summary: Archive public Git Repos and Gists from GitHub
3
+ Version: 0.1.12
4
+ Summary: Backup and archive Git Repos and Gists from GitHub
5
5
  Author: Corey Goldberg
6
6
  Maintainer: Corey Goldberg
7
7
  License-Expression: MIT
@@ -25,7 +25,7 @@ Dynamic: license-file
25
25
 
26
26
  # githubtakeout
27
27
 
28
- ## Archive Git Repos and Gists from GitHub
28
+ ## Backup and archive Git Repos and Gists from GitHub
29
29
 
30
30
  ---
31
31
 
@@ -38,32 +38,30 @@ Dynamic: license-file
38
38
 
39
39
  ## About:
40
40
 
41
- `githubtakeout` is a data export tool for archiving Git repositories hosted on GitHub.
42
- It clones a user's repos and creates an archive of each.
41
+ `githubtakeout` is a data export tool for backing up and archiving Git
42
+ repositories hosted on GitHub. It clones a user's repos and creates an archive
43
+ of each.
43
44
 
44
- It supports public/private repos and public/secret gists. By default, it doesn't save
45
- commit history or branches (`.git` directory), or Gist repositories (both can be enabled
46
- with command line options).
45
+ It supports public/private repos and public/secret gists. By default, it
46
+ doesn't save commit history or branches (`.git` directory), or Gist
47
+ repositories (both can be enabled with command line options).
47
48
 
48
- When you run the program, archives of your repos will be saved in a directory named
49
- `backups` inside your current working directory, unless a different location is specified
50
- using the `--dir` option.
49
+ When you run the program, archives of your repos will be saved in a directory
50
+ named `backups` inside your current working directory, unless a different
51
+ location is specified using the `--dir` option.
51
52
 
52
- Archives are saved in compressed zip format (`.zip`) by default, but can also be saved
53
- as tarballs (`.tar.gz`) using the `--format=tar` option.
53
+ Archives are saved in compressed zip format (`.zip`) by default. You can also
54
+ save as tarballs (`.tar.gz`) using the `--format=tar` option, or skip archiving
55
+ using the `--format=none` option.
54
56
 
55
57
  ## Requirements:
56
58
 
57
59
  - Python 3.12+
58
60
  - Git 1.7+
59
- - Python packages:
60
- - [GitPython][pypi-gitpython]
61
- - [PyGithub][pypi-pygithub]
62
- - [rich][pypi-rich]
63
61
 
64
62
  ## Installation:
65
63
 
66
- Install from [PyPI][pypyi-githubtakeout]:
64
+ #### Install from [PyPI][pypi-githubtakeout]:
67
65
 
68
66
  ```
69
67
  pip install githubtakeout
@@ -71,46 +69,48 @@ pip install githubtakeout
71
69
 
72
70
  ## Authentication:
73
71
 
74
- By default, `githubtakeout` will only retrieve an account's public repos. To access private repos and secret gists,
75
- you need to authenticate.
72
+ By default, `githubtakeout` will only retrieve an account's public repos. To
73
+ access private repos and secret gists, you need to authenticate.
76
74
 
77
- First, you must create a [personal access token][github-pat] on Github (either a fine-grained or classic personal
78
- access token). Once you have a token, you can set the `GITHUB_TOKEN` environment variable:
75
+ First, you must create a [personal access token][github-pat] on Github (either
76
+ a fine-grained or classic personal access token). Once you have a token, you
77
+ can set the `GITHUB_TOKEN` environment variable:
79
78
 
80
79
  ```
81
80
  $ export GITHUB_TOKEN=<access token>
82
81
  ```
83
82
 
84
- If you prefer to be prompted for your token each time you run the program, use the `--token` argument.
83
+ If you prefer to be prompted for your token each time you run the program, use
84
+ the `--token` argument.
85
85
 
86
- ### CLI Options:
86
+ ## CLI Options:
87
87
 
88
88
  ```
89
- usage: githubtakeout [-h] [--dir DIR] [--format {tar,zip}] [--gists] [--history] [--list] [--token] username
89
+ usage: githubtakeout [-h] [--dir DIR] [--format {tar,zip,none}] [--gists] [--history] [--list] [--token] username
90
90
 
91
91
  positional arguments:
92
- username github username
92
+ username github username
93
93
 
94
94
  options:
95
- -h, --help show this help message and exit
96
- --dir DIR output directory (default: ./)
97
- --format {tar,zip} archive format (default: zip)
98
- --gists include gists
99
- --history include commit history and branches (.git directory)
100
- --list list repos only
101
- --token prompt for auth token
95
+ -h, --help show this help message and exit
96
+ --dir DIR output directory (default: .)
97
+ --format {tar,zip,none} archive format (default: zip)
98
+ --gists include gists
99
+ --history include commit history and branches (.git directory)
100
+ --list list repos only
101
+ --token prompt for auth token
102
102
  ```
103
103
 
104
104
  ## Usage Examples:
105
105
 
106
- ### Install from PyPI with pipx, Run:
106
+ #### Install from PyPI with pipx, Run:
107
107
 
108
108
  ```
109
109
  pipx install githubtakeout
110
110
  githubtakeout <github username>
111
111
  ```
112
112
 
113
- ### Clone Repo, Create/Activate Virtual Environment, Install from Source, Run:
113
+ #### Clone Repo, Create/Activate Virtual Environment, Install from Source, Run:
114
114
 
115
115
  ```
116
116
  git clone git@github.com:cgoldberg/githubtakeout.git
@@ -121,12 +121,8 @@ pip install .
121
121
  githubtakeout <github username>
122
122
  ```
123
123
 
124
-
125
124
  [github-home]: https://github.com/cgoldberg
126
125
  [github-repo]: https://github.com/cgoldberg/sudokubot
127
126
  [github-pat]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
128
127
  [pypi-githubtakeout]: https://pypi.org/project/githubtakeout
129
- [pypi-gitpython]: https://pypi.org/project/GitPython
130
- [pypi-pygithub]: https://pypi.org/project/PyGithub
131
- [pypi-rich]: https://pypi.org/project/rich
132
128
  [mit-license]: https://raw.githubusercontent.com/cgoldberg/githubtakeout/refs/heads/master/LICENSE
@@ -0,0 +1,103 @@
1
+ # githubtakeout
2
+
3
+ ## Backup and 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 backing up and archiving Git
17
+ repositories hosted on GitHub. It clones a user's repos and creates an archive
18
+ of each.
19
+
20
+ It supports public/private repos and public/secret gists. By default, it
21
+ doesn't save commit history or branches (`.git` directory), or Gist
22
+ repositories (both can be enabled with command line options).
23
+
24
+ When you run the program, archives of your repos will be saved in a directory
25
+ named `backups` inside your current working directory, unless a different
26
+ location is specified using the `--dir` option.
27
+
28
+ Archives are saved in compressed zip format (`.zip`) by default. You can also
29
+ save as tarballs (`.tar.gz`) using the `--format=tar` option, or skip archiving
30
+ using the `--format=none` option.
31
+
32
+ ## Requirements:
33
+
34
+ - Python 3.12+
35
+ - Git 1.7+
36
+
37
+ ## Installation:
38
+
39
+ #### Install from [PyPI][pypi-githubtakeout]:
40
+
41
+ ```
42
+ pip install githubtakeout
43
+ ```
44
+
45
+ ## Authentication:
46
+
47
+ By default, `githubtakeout` will only retrieve an account's public repos. To
48
+ access private repos and secret gists, you need to authenticate.
49
+
50
+ First, you must create a [personal access token][github-pat] on Github (either
51
+ a fine-grained or classic personal access token). Once you have a token, you
52
+ can set the `GITHUB_TOKEN` environment variable:
53
+
54
+ ```
55
+ $ export GITHUB_TOKEN=<access token>
56
+ ```
57
+
58
+ If you prefer to be prompted for your token each time you run the program, use
59
+ the `--token` argument.
60
+
61
+ ## CLI Options:
62
+
63
+ ```
64
+ usage: githubtakeout [-h] [--dir DIR] [--format {tar,zip,none}] [--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,none} 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
+ [github-home]: https://github.com/cgoldberg
100
+ [github-repo]: https://github.com/cgoldberg/sudokubot
101
+ [github-pat]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
102
+ [pypi-githubtakeout]: https://pypi.org/project/githubtakeout
103
+ [mit-license]: https://raw.githubusercontent.com/cgoldberg/githubtakeout/refs/heads/master/LICENSE
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "githubtakeout"
7
- version = "0.1.10"
8
- description = "Archive public Git Repos and Gists from GitHub"
7
+ version = "0.1.12"
8
+ description = "Backup and archive Git Repos and Gists from GitHub"
9
9
  license = "MIT"
10
10
  license-files = ["LICENSE"]
11
11
  authors = [{name = "Corey Goldberg"}]
@@ -35,22 +35,51 @@ homepage = "https://github.com/cgoldberg/githubtakeout"
35
35
  source = "https://github.com/cgoldberg/githubtakeout"
36
36
  download = "https://pypi.org/project/githubtakeout"
37
37
 
38
+ [dependency-groups]
39
+ dev = [
40
+ "tox",
41
+ ]
42
+ lint = [
43
+ "black",
44
+ "refurb",
45
+ "ruff",
46
+ ]
47
+ validate = [
48
+ "packaging",
49
+ "validate-pyproject",
50
+ ]
51
+
38
52
  [tool.setuptools]
39
53
  package-dir = {"" = "src"}
40
54
 
41
55
  [tool.black]
42
- line-length = 88
43
- target-version = ["py39", "py310", "py311", "py312", "py313"]
56
+ line-length = 120
57
+ target-version = [
58
+ "py312", "py313"
59
+ ]
44
60
 
45
61
  [tool.ruff]
46
- line-length = 88
62
+ line-length = 120
47
63
  respect-gitignore = true
48
64
  target-version = "py312"
49
65
 
50
66
  [tool.ruff.lint]
51
- extend-select = ["E4", "E7", "E9", "F", "I", "E501", "RUF022"]
67
+ select = [
68
+ "D", "E", "F", "I", "PT", "RUF", "TID", "W"
69
+ ]
70
+ extend-ignore = [
71
+ "D100", "D101", "D102", "D103", "D104", "D105", "D106", "D107", "D203",
72
+ "D205", "D211", "D213", "D400", "D401", "RUF012"
73
+ ]
52
74
  fixable = ["ALL"]
53
75
 
54
76
  [tool.ruff.format]
55
77
  docstring-code-format = true
56
- docstring-code-line-length = 88
78
+ docstring-code-line-length = 120
79
+
80
+ [tool.refurb]
81
+ python_version = "3.9"
82
+ enable_all = true
83
+ disable = [
84
+ "FURB104", "FURB107", "FURB147", "FURB173", "FURB183", "FURB184"
85
+ ]
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: githubtakeout
3
- Version: 0.1.10
4
- Summary: Archive public Git Repos and Gists from GitHub
3
+ Version: 0.1.12
4
+ Summary: Backup and archive Git Repos and Gists from GitHub
5
5
  Author: Corey Goldberg
6
6
  Maintainer: Corey Goldberg
7
7
  License-Expression: MIT
@@ -25,7 +25,7 @@ Dynamic: license-file
25
25
 
26
26
  # githubtakeout
27
27
 
28
- ## Archive Git Repos and Gists from GitHub
28
+ ## Backup and archive Git Repos and Gists from GitHub
29
29
 
30
30
  ---
31
31
 
@@ -38,32 +38,30 @@ Dynamic: license-file
38
38
 
39
39
  ## About:
40
40
 
41
- `githubtakeout` is a data export tool for archiving Git repositories hosted on GitHub.
42
- It clones a user's repos and creates an archive of each.
41
+ `githubtakeout` is a data export tool for backing up and archiving Git
42
+ repositories hosted on GitHub. It clones a user's repos and creates an archive
43
+ of each.
43
44
 
44
- It supports public/private repos and public/secret gists. By default, it doesn't save
45
- commit history or branches (`.git` directory), or Gist repositories (both can be enabled
46
- with command line options).
45
+ It supports public/private repos and public/secret gists. By default, it
46
+ doesn't save commit history or branches (`.git` directory), or Gist
47
+ repositories (both can be enabled with command line options).
47
48
 
48
- When you run the program, archives of your repos will be saved in a directory named
49
- `backups` inside your current working directory, unless a different location is specified
50
- using the `--dir` option.
49
+ When you run the program, archives of your repos will be saved in a directory
50
+ named `backups` inside your current working directory, unless a different
51
+ location is specified using the `--dir` option.
51
52
 
52
- Archives are saved in compressed zip format (`.zip`) by default, but can also be saved
53
- as tarballs (`.tar.gz`) using the `--format=tar` option.
53
+ Archives are saved in compressed zip format (`.zip`) by default. You can also
54
+ save as tarballs (`.tar.gz`) using the `--format=tar` option, or skip archiving
55
+ using the `--format=none` option.
54
56
 
55
57
  ## Requirements:
56
58
 
57
59
  - Python 3.12+
58
60
  - Git 1.7+
59
- - Python packages:
60
- - [GitPython][pypi-gitpython]
61
- - [PyGithub][pypi-pygithub]
62
- - [rich][pypi-rich]
63
61
 
64
62
  ## Installation:
65
63
 
66
- Install from [PyPI][pypyi-githubtakeout]:
64
+ #### Install from [PyPI][pypi-githubtakeout]:
67
65
 
68
66
  ```
69
67
  pip install githubtakeout
@@ -71,46 +69,48 @@ pip install githubtakeout
71
69
 
72
70
  ## Authentication:
73
71
 
74
- By default, `githubtakeout` will only retrieve an account's public repos. To access private repos and secret gists,
75
- you need to authenticate.
72
+ By default, `githubtakeout` will only retrieve an account's public repos. To
73
+ access private repos and secret gists, you need to authenticate.
76
74
 
77
- First, you must create a [personal access token][github-pat] on Github (either a fine-grained or classic personal
78
- access token). Once you have a token, you can set the `GITHUB_TOKEN` environment variable:
75
+ First, you must create a [personal access token][github-pat] on Github (either
76
+ a fine-grained or classic personal access token). Once you have a token, you
77
+ can set the `GITHUB_TOKEN` environment variable:
79
78
 
80
79
  ```
81
80
  $ export GITHUB_TOKEN=<access token>
82
81
  ```
83
82
 
84
- If you prefer to be prompted for your token each time you run the program, use the `--token` argument.
83
+ If you prefer to be prompted for your token each time you run the program, use
84
+ the `--token` argument.
85
85
 
86
- ### CLI Options:
86
+ ## CLI Options:
87
87
 
88
88
  ```
89
- usage: githubtakeout [-h] [--dir DIR] [--format {tar,zip}] [--gists] [--history] [--list] [--token] username
89
+ usage: githubtakeout [-h] [--dir DIR] [--format {tar,zip,none}] [--gists] [--history] [--list] [--token] username
90
90
 
91
91
  positional arguments:
92
- username github username
92
+ username github username
93
93
 
94
94
  options:
95
- -h, --help show this help message and exit
96
- --dir DIR output directory (default: ./)
97
- --format {tar,zip} archive format (default: zip)
98
- --gists include gists
99
- --history include commit history and branches (.git directory)
100
- --list list repos only
101
- --token prompt for auth token
95
+ -h, --help show this help message and exit
96
+ --dir DIR output directory (default: .)
97
+ --format {tar,zip,none} archive format (default: zip)
98
+ --gists include gists
99
+ --history include commit history and branches (.git directory)
100
+ --list list repos only
101
+ --token prompt for auth token
102
102
  ```
103
103
 
104
104
  ## Usage Examples:
105
105
 
106
- ### Install from PyPI with pipx, Run:
106
+ #### Install from PyPI with pipx, Run:
107
107
 
108
108
  ```
109
109
  pipx install githubtakeout
110
110
  githubtakeout <github username>
111
111
  ```
112
112
 
113
- ### Clone Repo, Create/Activate Virtual Environment, Install from Source, Run:
113
+ #### Clone Repo, Create/Activate Virtual Environment, Install from Source, Run:
114
114
 
115
115
  ```
116
116
  git clone git@github.com:cgoldberg/githubtakeout.git
@@ -121,12 +121,8 @@ pip install .
121
121
  githubtakeout <github username>
122
122
  ```
123
123
 
124
-
125
124
  [github-home]: https://github.com/cgoldberg
126
125
  [github-repo]: https://github.com/cgoldberg/sudokubot
127
126
  [github-pat]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens
128
127
  [pypi-githubtakeout]: https://pypi.org/project/githubtakeout
129
- [pypi-gitpython]: https://pypi.org/project/GitPython
130
- [pypi-pygithub]: https://pypi.org/project/PyGithub
131
- [pypi-rich]: https://pypi.org/project/rich
132
128
  [mit-license]: https://raw.githubusercontent.com/cgoldberg/githubtakeout/refs/heads/master/LICENSE
@@ -1,7 +1,7 @@
1
- # Corey Goldberg, 2025
1
+ # Copyright (c) 2015-2025 Corey Goldberg
2
2
  # License: MIT
3
3
 
4
- """Archive Git Repos and Gists from GitHub"""
4
+ """Backup and archive Git Repos and Gists from GitHub."""
5
5
 
6
6
  import argparse
7
7
  import getpass
@@ -22,7 +22,7 @@ import github
22
22
 
23
23
  from progress import GitProgress
24
24
 
25
- ARCHIVE_FORMATS = ("tar", "zip")
25
+ ARCHIVE_FORMATS = ("tar", "zip", "none")
26
26
 
27
27
  logging.basicConfig(level=logging.INFO, format="%(message)s")
28
28
  logger = logging.getLogger(__name__)
@@ -32,7 +32,7 @@ def convert_size(size_bytes):
32
32
  if size_bytes == 0:
33
33
  return "0 B"
34
34
  size_name = ("B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB")
35
- i = int(math.floor(math.log(size_bytes, 1024)))
35
+ i = math.floor(math.log(size_bytes, 1024))
36
36
  p = math.pow(1024, i)
37
37
  s = round(size_bytes / p, 2)
38
38
  return f"{s} {size_name[i]}"
@@ -52,6 +52,8 @@ def add_creds(url, username, token):
52
52
  def archive(local_repo_dir, archive_format="zip", is_gist=False):
53
53
  if archive_format not in ARCHIVE_FORMATS:
54
54
  raise ValueError(f"{archive_format} is not a valid archive format")
55
+ if archive_format == "none":
56
+ return None
55
57
  base_name = os.path.basename(local_repo_dir)
56
58
  extension = "tar.gz" if archive_format == "tar" else archive_format
57
59
  archive_name = f"{base_name}.{extension}"
@@ -101,9 +103,7 @@ def clone(repo_url, local_repo_dir, include_history):
101
103
  pass
102
104
 
103
105
 
104
- def clone_and_archive_repo(
105
- repo_url, local_repo_dir, archive_format, include_history, is_gist=False
106
- ):
106
+ def clone_and_archive_repo(repo_url, local_repo_dir, archive_format, include_history, is_gist=False):
107
107
  def remove_readonly(func, path, _):
108
108
  # This is necessary so rmtree() doesn't fail if there are any readonly
109
109
  # dirs/files when trying to delete. This seems to happen after cloning on
@@ -134,45 +134,26 @@ def clone_and_archive_repo(
134
134
  except FileNotFoundError:
135
135
  pass
136
136
  archive_path = archive(local_repo_dir, archive_format, is_gist)
137
- size = convert_size(os.path.getsize(archive_path))
138
- logger.info(f"archive size: {size}")
139
- logger.info("deleting repo")
140
- try:
141
- # delete repo after archive is created
142
- shutil.rmtree(local_repo_dir, onexc=remove_readonly)
143
- except FileNotFoundError:
144
- pass
137
+ if archive_path:
138
+ size = convert_size(os.path.getsize(archive_path))
139
+ logger.info(f"archive size: {size}")
140
+ logger.info("deleting repo")
141
+ try:
142
+ # delete repo after archive is created
143
+ shutil.rmtree(local_repo_dir, onexc=remove_readonly)
144
+ except FileNotFoundError:
145
+ pass
145
146
  elapsed = default_timer() - start
146
147
  base_name = os.path.basename(local_repo_dir)
147
148
  logger.info(f"successfully backed up '{base_name}' repo in {elapsed:.3f} secs\n")
148
149
 
149
150
 
150
- def get_user(username, prompt_token):
151
- if prompt_token:
152
- token = getpass.getpass("Token:")
153
- if not token:
154
- sys.exit("error: auth token cannot be empty")
151
+ def get_repos(username, token, include_gists):
152
+ if token is not None:
153
+ # you need to be authenticated and then call the API
154
+ # with no username to get public and private repos
155
155
  auth = github.Auth.Token(token)
156
156
  gh = github.Github(auth=auth)
157
- else:
158
- token = os.getenv("GITHUB_TOKEN")
159
- if token is not None:
160
- auth = github.Auth.Token(token)
161
- gh = github.Github(auth=auth)
162
- else:
163
- gh = github.Github()
164
- if token is None:
165
- try:
166
- user = gh.get_user(username)
167
- except github.GithubException as e:
168
- if e.data["status"] == "404":
169
- sys.exit(f"error: user '{username}' not found")
170
- else:
171
- raise e
172
- repos = user.get_repos()
173
- else:
174
- # you need to be authenticated and then call the API
175
- # with no username to get private repos
176
157
  user = gh.get_user()
177
158
  repos = user.get_repos(affiliation="owner")
178
159
  try:
@@ -183,8 +164,31 @@ def get_user(username, prompt_token):
183
164
  sys.exit(f"error: invalid auth token for user '{username}'")
184
165
  else:
185
166
  raise e
186
- gists = user.get_gists()
187
- return user, repos, gists, token
167
+ else:
168
+ gh = github.Github()
169
+ try:
170
+ user = gh.get_user(username)
171
+ except github.GithubException as e:
172
+ if e.data["status"] == "404":
173
+ sys.exit(f"error: user '{username}' not found")
174
+ else:
175
+ raise e
176
+ repos = user.get_repos()
177
+ if include_gists:
178
+ gists = user.get_gists()
179
+ else:
180
+ gists = None
181
+ return repos, gists
182
+
183
+
184
+ def get_token(prompt_for_token):
185
+ if prompt_for_token:
186
+ token = getpass.getpass("Token:")
187
+ if not token:
188
+ sys.exit("error: auth token cannot be empty")
189
+ else:
190
+ token = os.getenv("GITHUB_TOKEN")
191
+ return token
188
192
 
189
193
 
190
194
  def run(
@@ -194,10 +198,11 @@ def run(
194
198
  include_gists,
195
199
  include_history,
196
200
  list_only,
197
- prompt_token,
201
+ prompt_for_token,
198
202
  ):
199
203
  working_dir = os.path.join(base_dir, "backups")
200
- user, repos, gists, token = get_user(username, prompt_token)
204
+ token = get_token(prompt_for_token)
205
+ repos, gists = get_repos(username, token, include_gists)
201
206
  num_repos = repos.totalCount
202
207
  if not list_only:
203
208
  logger.info(f"creating archives in: {working_dir}\n")
@@ -209,7 +214,7 @@ def run(
209
214
  logger.info(url)
210
215
  else:
211
216
  clone_and_archive_repo(url, local_repo_dir, archive_format, include_history)
212
- if include_gists:
217
+ if gists is not None:
213
218
  num_gists = gists.totalCount
214
219
  logger.info("")
215
220
  logger.info(f"found {num_gists} gists for user '{username}'\n")
@@ -219,20 +224,22 @@ def run(
219
224
  if list_only:
220
225
  logger.info(url)
221
226
  else:
222
- clone_and_archive_repo(
223
- url, local_repo_dir, archive_format, include_history, is_gist=True
224
- )
227
+ clone_and_archive_repo(url, local_repo_dir, archive_format, include_history, is_gist=True)
225
228
 
226
229
 
227
230
  def main():
228
231
  if sys.version_info < (3, 12):
229
232
  sys.exit("sorry, this program requires Python 3.12+")
230
- parser = argparse.ArgumentParser()
233
+
234
+ def formatter(prog):
235
+ return argparse.HelpFormatter(prog, max_help_position=30)
236
+
237
+ parser = argparse.ArgumentParser(formatter_class=formatter)
231
238
  parser.add_argument("username", help="github username")
232
239
  parser.add_argument(
233
240
  "--dir",
234
241
  default=os.getcwd(),
235
- help="output directory (default: ./)",
242
+ help="output directory (default: .)",
236
243
  )
237
244
  parser.add_argument(
238
245
  "--format",
@@ -240,21 +247,15 @@ def main():
240
247
  default="zip",
241
248
  help="archive format (default: %(default)s)",
242
249
  )
243
- parser.add_argument(
244
- "--gists", action="store_true", default=False, help="include gists"
245
- )
250
+ parser.add_argument("--gists", action="store_true", default=False, help="include gists")
246
251
  parser.add_argument(
247
252
  "--history",
248
253
  action="store_true",
249
254
  default=False,
250
255
  help="include commit history and branches (.git directory)",
251
256
  )
252
- parser.add_argument(
253
- "--list", action="store_true", default=False, help="list repos only"
254
- )
255
- parser.add_argument(
256
- "--token", action="store_true", default=False, help="prompt for auth token"
257
- )
257
+ parser.add_argument("--list", action="store_true", default=False, help="list repos only")
258
+ parser.add_argument("--token", action="store_true", default=False, help="prompt for auth token")
258
259
  args = parser.parse_args()
259
260
  try:
260
261
  run(
@@ -264,7 +265,7 @@ def main():
264
265
  include_gists=args.gists,
265
266
  include_history=args.history,
266
267
  list_only=args.list,
267
- prompt_token=args.token,
268
+ prompt_for_token=args.token,
268
269
  )
269
270
  except KeyboardInterrupt:
270
271
  sys.exit("\nexiting program ...")
@@ -1,8 +1,12 @@
1
+ # Copyright (c) 2025 Corey Goldberg
2
+ # License: MIT
3
+ # adapted from: https://stackoverflow.com/a/71285627/16148
4
+
5
+ """Progress bar for cloning Git repos."""
6
+
1
7
  import git
2
8
  from rich import console, progress
3
9
 
4
- # adapted from: https://stackoverflow.com/a/71285627/16148
5
-
6
10
 
7
11
  class GitProgress(git.RemoteProgress):
8
12
  OP_CODES = [
@@ -16,9 +20,7 @@ class GitProgress(git.RemoteProgress):
16
20
  "RESOLVING",
17
21
  "WRITING",
18
22
  ]
19
- OP_CODE_MAP = {
20
- getattr(git.RemoteProgress, _op_code): _op_code for _op_code in OP_CODES
21
- }
23
+ OP_CODE_MAP = {getattr(git.RemoteProgress, _op_code): _op_code for _op_code in OP_CODES}
22
24
 
23
25
  def __init__(self):
24
26
  super().__init__()
@@ -1,107 +0,0 @@
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
File without changes
File without changes