gitstore 0.2.0__tar.gz → 0.2.2__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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitstore
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Utilities to encrypt files/directories with utilitz and exchange them through GitHub repositories.
5
5
  Author: artitzco
6
6
  License: MIT
@@ -46,7 +46,7 @@ gitstore/
46
46
  ## Core API
47
47
 
48
48
  ```python
49
- from gitstore import upload_to_github, download_from_github
49
+ from gitstore import upload_to_github, restore_from_github, restore_from_file
50
50
  ```
51
51
 
52
52
  ## Upload
@@ -106,10 +106,10 @@ folder/documento
106
106
  ## Download
107
107
 
108
108
  ```python
109
- from gitstore import download_from_github
109
+ from gitstore import restore_from_github
110
110
 
111
- output_path = download_from_github(
112
- github_url="https://github.com/USER/REPO/blob/main/vault/documento_ventas_q2.asc",
111
+ output_path = restore_from_github(
112
+ github_raw_url="https://raw.githubusercontent.com/USER/REPO/main/vault/documento_ventas_q2.asc",
113
113
  password=None, # default: uses GITSTORE_PASSWORD
114
114
  output_path=None, # default: restores in the current working directory
115
115
  overwrite=False, # default
@@ -118,18 +118,38 @@ output_path = download_from_github(
118
118
  print(output_path)
119
119
  ```
120
120
 
121
+ Local restore (no network):
122
+
123
+ ```python
124
+ from gitstore import restore_from_file
125
+
126
+ output_path = restore_from_file(
127
+ encrypted_file_path="C:/downloads/documento_ventas_q2.asc",
128
+ password=None, # default: uses GITSTORE_PASSWORD
129
+ output_path=None, # optional
130
+ overwrite=False, # default
131
+ )
132
+ print(output_path)
133
+ ```
134
+
135
+ Tip:
136
+
137
+ - use `restore_from_file(...)` when the target machine has SSL/certificate restrictions and you prefer manual transfer of the `.asc` file.
138
+
121
139
  Download behavior:
122
140
 
123
- - accepts normal GitHub file URLs (`github.com/.../blob/...`) and raw URLs
141
+ - expects RAW GitHub URLs (`raw.githubusercontent.com/...`) as primary input
142
+ - also accepts `github.com/.../blob/...` and normalizes automatically
124
143
  - skips download when `output_path` already exists and matches the remote `source_hash` in `vault/index.json`
125
144
  - set `force_download=True` to download even when the local output appears aligned
126
145
  - downloads the encrypted `.asc` file to a temporary location
127
146
  - restores files or directories automatically with `utilitz.crypto`
128
147
  - removes the temporary encrypted file after restore
148
+ - supports local decode with `restore_from_file(...)` when manual download is preferred
129
149
 
130
150
  ## Password Source
131
151
 
132
- `upload_to_github` and `download_from_github` auto-detect password from:
152
+ `upload_to_github`, `restore_from_github`, and `restore_from_file` auto-detect password from:
133
153
 
134
154
  - `GITSTORE_PASSWORD`
135
155
 
@@ -1,136 +1,145 @@
1
- Metadata-Version: 2.4
2
- Name: gitstore
3
- Version: 0.2.0
4
- Summary: Utilities to encrypt files/directories with utilitz and exchange them through GitHub repositories.
5
- Author: artitzco
6
- License: MIT
7
- Requires-Python: >=3.10
8
- Description-Content-Type: text/markdown
9
- Requires-Dist: requests>=2.31.0
10
- Requires-Dist: utilitz[crypto]
11
-
12
- # gitstore
13
-
14
- `gitstore` is a focused Python package for one goal:
15
-
16
- - upload encrypted files/folders to a GitHub-backed repo
17
- - download and restore encrypted GitHub files later
18
-
19
- ## Installation
20
-
21
- ```bash
22
- pip install gitstore
23
- ```
24
-
25
- ## Dependency on `utilitz`
26
-
27
- This project depends on:
28
-
29
- - `utilitz[crypto]`
30
- - `requests`
31
-
32
- ## Project Structure
33
-
34
- ```text
35
- gitstore/
36
- src/gitstore/
37
- __init__.py
38
- client.py
39
- config.py
40
- crypto_ops.py
41
- github_ops.py
42
- pyproject.toml
43
- README.md
44
- ```
45
-
46
- ## Core API
47
-
48
- ```python
49
- from gitstore import upload_to_github, download_from_github
50
- ```
51
-
52
- ## Upload
53
-
54
- ```python
55
- from gitstore import upload_to_github
56
-
57
- record = upload_to_github(
58
- source_path="C:/data/documento.pdf", # file or directory
59
- name="documento_ventas_q2", # logical name only
60
- repo_path="C:/repos/my-publish-repo", # required
61
- password=None, # default: uses GITSTORE_PASSWORD
62
- vault_dir="vault", # default
63
- request_timeout=60, # default
64
- security_level="high", # default
65
- replace_existing=True, # default
66
- force_upload=False, # default
67
- commit_message=None, # default: automatic message
68
- )
69
- print(record)
70
- ```
71
-
72
- Upload behavior:
73
-
74
- - computes `source_hash` from source content before encryption
75
- - skips upload if same `name` already has same `source_hash`
76
- - set `force_upload=True` to upload even when the current source matches the remote metadata
77
- - stores artifact as `vault/<name>.asc`
78
- - stores metadata in `vault/index.json`
79
- - removes temporary encrypted file after processing
80
-
81
- ## Valid Names
82
-
83
- `name` is the logical identifier used to upload an artifact.
84
- It is intentionally strict to keep Git paths predictable:
85
-
86
- - allowed characters: letters, numbers, dots, underscores, and hyphens
87
- - must start with a letter or number
88
- - spaces and path separators are not allowed
89
-
90
- Valid examples:
91
-
92
- ```text
93
- documento_ventas_q2
94
- maindb-version-0.1
95
- backup.2026_05
96
- ```
97
-
98
- Invalid examples:
99
-
100
- ```text
101
- maindb -version 0.1
102
- ../secret
103
- folder/documento
104
- ```
105
-
106
- ## Download
107
-
108
- ```python
109
- from gitstore import download_from_github
110
-
111
- output_path = download_from_github(
112
- github_url="https://github.com/USER/REPO/blob/main/vault/documento_ventas_q2.asc",
113
- password=None, # default: uses GITSTORE_PASSWORD
114
- output_path=None, # default: restores in the current working directory
115
- overwrite=False, # default
116
- force_download=False, # default
117
- )
118
- print(output_path)
119
- ```
120
-
121
- Download behavior:
122
-
123
- - accepts normal GitHub file URLs (`github.com/.../blob/...`) and raw URLs
124
- - skips download when `output_path` already exists and matches the remote `source_hash` in `vault/index.json`
125
- - set `force_download=True` to download even when the local output appears aligned
126
- - downloads the encrypted `.asc` file to a temporary location
127
- - restores files or directories automatically with `utilitz.crypto`
128
- - removes the temporary encrypted file after restore
129
-
130
- ## Password Source
131
-
132
- `upload_to_github` and `download_from_github` auto-detect password from:
133
-
134
- - `GITSTORE_PASSWORD`
135
-
136
- If `password` is not passed, the environment variable is used.
1
+ # gitstore
2
+
3
+ `gitstore` is a focused Python package for one goal:
4
+
5
+ - upload encrypted files/folders to a GitHub-backed repo
6
+ - download and restore encrypted GitHub files later
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ pip install gitstore
12
+ ```
13
+
14
+ ## Dependency on `utilitz`
15
+
16
+ This project depends on:
17
+
18
+ - `utilitz[crypto]`
19
+ - `requests`
20
+
21
+ ## Project Structure
22
+
23
+ ```text
24
+ gitstore/
25
+ src/gitstore/
26
+ __init__.py
27
+ client.py
28
+ config.py
29
+ crypto_ops.py
30
+ github_ops.py
31
+ pyproject.toml
32
+ README.md
33
+ ```
34
+
35
+ ## Core API
36
+
37
+ ```python
38
+ from gitstore import upload_to_github, restore_from_github, restore_from_file
39
+ ```
40
+
41
+ ## Upload
42
+
43
+ ```python
44
+ from gitstore import upload_to_github
45
+
46
+ record = upload_to_github(
47
+ source_path="C:/data/documento.pdf", # file or directory
48
+ name="documento_ventas_q2", # logical name only
49
+ repo_path="C:/repos/my-publish-repo", # required
50
+ password=None, # default: uses GITSTORE_PASSWORD
51
+ vault_dir="vault", # default
52
+ request_timeout=60, # default
53
+ security_level="high", # default
54
+ replace_existing=True, # default
55
+ force_upload=False, # default
56
+ commit_message=None, # default: automatic message
57
+ )
58
+ print(record)
59
+ ```
60
+
61
+ Upload behavior:
62
+
63
+ - computes `source_hash` from source content before encryption
64
+ - skips upload if same `name` already has same `source_hash`
65
+ - set `force_upload=True` to upload even when the current source matches the remote metadata
66
+ - stores artifact as `vault/<name>.asc`
67
+ - stores metadata in `vault/index.json`
68
+ - removes temporary encrypted file after processing
69
+
70
+ ## Valid Names
71
+
72
+ `name` is the logical identifier used to upload an artifact.
73
+ It is intentionally strict to keep Git paths predictable:
74
+
75
+ - allowed characters: letters, numbers, dots, underscores, and hyphens
76
+ - must start with a letter or number
77
+ - spaces and path separators are not allowed
78
+
79
+ Valid examples:
80
+
81
+ ```text
82
+ documento_ventas_q2
83
+ maindb-version-0.1
84
+ backup.2026_05
85
+ ```
86
+
87
+ Invalid examples:
88
+
89
+ ```text
90
+ maindb -version 0.1
91
+ ../secret
92
+ folder/documento
93
+ ```
94
+
95
+ ## Download
96
+
97
+ ```python
98
+ from gitstore import restore_from_github
99
+
100
+ output_path = restore_from_github(
101
+ github_raw_url="https://raw.githubusercontent.com/USER/REPO/main/vault/documento_ventas_q2.asc",
102
+ password=None, # default: uses GITSTORE_PASSWORD
103
+ output_path=None, # default: restores in the current working directory
104
+ overwrite=False, # default
105
+ force_download=False, # default
106
+ )
107
+ print(output_path)
108
+ ```
109
+
110
+ Local restore (no network):
111
+
112
+ ```python
113
+ from gitstore import restore_from_file
114
+
115
+ output_path = restore_from_file(
116
+ encrypted_file_path="C:/downloads/documento_ventas_q2.asc",
117
+ password=None, # default: uses GITSTORE_PASSWORD
118
+ output_path=None, # optional
119
+ overwrite=False, # default
120
+ )
121
+ print(output_path)
122
+ ```
123
+
124
+ Tip:
125
+
126
+ - use `restore_from_file(...)` when the target machine has SSL/certificate restrictions and you prefer manual transfer of the `.asc` file.
127
+
128
+ Download behavior:
129
+
130
+ - expects RAW GitHub URLs (`raw.githubusercontent.com/...`) as primary input
131
+ - also accepts `github.com/.../blob/...` and normalizes automatically
132
+ - skips download when `output_path` already exists and matches the remote `source_hash` in `vault/index.json`
133
+ - set `force_download=True` to download even when the local output appears aligned
134
+ - downloads the encrypted `.asc` file to a temporary location
135
+ - restores files or directories automatically with `utilitz.crypto`
136
+ - removes the temporary encrypted file after restore
137
+ - supports local decode with `restore_from_file(...)` when manual download is preferred
138
+
139
+ ## Password Source
140
+
141
+ `upload_to_github`, `restore_from_github`, and `restore_from_file` auto-detect password from:
142
+
143
+ - `GITSTORE_PASSWORD`
144
+
145
+ If `password` is not passed, the environment variable is used.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "gitstore"
7
- version = "0.2.0"
7
+ version = "0.2.2"
8
8
  description = "Utilities to encrypt files/directories with utilitz and exchange them through GitHub repositories."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,13 +1,15 @@
1
1
  from .client import (
2
2
  DEFAULT_PASSWORD_ENV_VAR,
3
3
  StoredArtifact,
4
- download_from_github,
4
+ restore_from_github,
5
+ restore_from_file,
5
6
  upload_to_github,
6
7
  )
7
8
 
8
9
  __all__ = [
9
10
  "StoredArtifact",
10
- "download_from_github",
11
+ "restore_from_github",
12
+ "restore_from_file",
11
13
  "upload_to_github",
12
14
  "DEFAULT_PASSWORD_ENV_VAR",
13
15
  ]
@@ -96,8 +96,8 @@ def _hmac_source(path: Path, secret: str) -> str:
96
96
  return mac.hexdigest()
97
97
 
98
98
 
99
- def download_from_github(
100
- github_url: str,
99
+ def restore_from_github(
100
+ github_raw_url: str,
101
101
  password: str | None = None,
102
102
  output_path: str | None = None,
103
103
  overwrite: bool = False,
@@ -107,7 +107,7 @@ def download_from_github(
107
107
  ) -> str:
108
108
  resolved_password = _resolve_password(password, password_env_var)
109
109
  config = GitStoreConfig(password=resolved_password, request_timeout=request_timeout)
110
- raw_url = normalize_github_file_url(github_url)
110
+ raw_url = normalize_github_file_url(github_raw_url)
111
111
  if output_path is not None and not overwrite and not force_download:
112
112
  existing_output = Path(output_path).expanduser().resolve()
113
113
  if existing_output.exists():
@@ -145,6 +145,28 @@ def download_from_github(
145
145
  shutil.rmtree(temp_dir, ignore_errors=True)
146
146
 
147
147
 
148
+ def restore_from_file(
149
+ encrypted_file_path: str,
150
+ password: str | None = None,
151
+ output_path: str | None = None,
152
+ overwrite: bool = False,
153
+ password_env_var: str = DEFAULT_PASSWORD_ENV_VAR,
154
+ ) -> str:
155
+ resolved_password = _resolve_password(password, password_env_var)
156
+ config = GitStoreConfig(password=resolved_password, request_timeout=60)
157
+ encrypted_file = Path(encrypted_file_path).expanduser().resolve()
158
+ if not encrypted_file.is_file():
159
+ raise FileNotFoundError(f"Encrypted file not found: {encrypted_file}")
160
+ restored_path = decrypt_auto(
161
+ encrypted_path=str(encrypted_file),
162
+ config=config,
163
+ output_path=output_path,
164
+ overwrite=overwrite,
165
+ )
166
+ print(f"[gitstore] Restored local artifact '{encrypted_file}' -> '{restored_path}'.")
167
+ return restored_path
168
+
169
+
148
170
  def _load_remote_record_for_artifact(raw_url: str, request_timeout: int) -> dict:
149
171
  manifest_url = raw_url.rsplit("/", 1)[0] + "/index.json"
150
172
  artifact_name = raw_url.rsplit("/", 1)[-1]
@@ -1,125 +1,156 @@
1
- # gitstore
2
-
3
- `gitstore` is a focused Python package for one goal:
4
-
5
- - upload encrypted files/folders to a GitHub-backed repo
6
- - download and restore encrypted GitHub files later
7
-
8
- ## Installation
9
-
10
- ```bash
11
- pip install gitstore
12
- ```
13
-
14
- ## Dependency on `utilitz`
15
-
16
- This project depends on:
17
-
18
- - `utilitz[crypto]`
19
- - `requests`
20
-
21
- ## Project Structure
22
-
23
- ```text
24
- gitstore/
25
- src/gitstore/
26
- __init__.py
27
- client.py
28
- config.py
29
- crypto_ops.py
30
- github_ops.py
31
- pyproject.toml
32
- README.md
33
- ```
34
-
35
- ## Core API
36
-
37
- ```python
38
- from gitstore import upload_to_github, download_from_github
39
- ```
40
-
41
- ## Upload
42
-
43
- ```python
44
- from gitstore import upload_to_github
45
-
46
- record = upload_to_github(
47
- source_path="C:/data/documento.pdf", # file or directory
48
- name="documento_ventas_q2", # logical name only
49
- repo_path="C:/repos/my-publish-repo", # required
50
- password=None, # default: uses GITSTORE_PASSWORD
51
- vault_dir="vault", # default
52
- request_timeout=60, # default
53
- security_level="high", # default
54
- replace_existing=True, # default
55
- force_upload=False, # default
56
- commit_message=None, # default: automatic message
57
- )
58
- print(record)
59
- ```
60
-
61
- Upload behavior:
62
-
63
- - computes `source_hash` from source content before encryption
64
- - skips upload if same `name` already has same `source_hash`
65
- - set `force_upload=True` to upload even when the current source matches the remote metadata
66
- - stores artifact as `vault/<name>.asc`
67
- - stores metadata in `vault/index.json`
68
- - removes temporary encrypted file after processing
69
-
70
- ## Valid Names
71
-
72
- `name` is the logical identifier used to upload an artifact.
73
- It is intentionally strict to keep Git paths predictable:
74
-
75
- - allowed characters: letters, numbers, dots, underscores, and hyphens
76
- - must start with a letter or number
77
- - spaces and path separators are not allowed
78
-
79
- Valid examples:
80
-
81
- ```text
82
- documento_ventas_q2
83
- maindb-version-0.1
84
- backup.2026_05
85
- ```
86
-
87
- Invalid examples:
88
-
89
- ```text
90
- maindb -version 0.1
91
- ../secret
92
- folder/documento
93
- ```
94
-
95
- ## Download
96
-
97
- ```python
98
- from gitstore import download_from_github
99
-
100
- output_path = download_from_github(
101
- github_url="https://github.com/USER/REPO/blob/main/vault/documento_ventas_q2.asc",
102
- password=None, # default: uses GITSTORE_PASSWORD
103
- output_path=None, # default: restores in the current working directory
104
- overwrite=False, # default
105
- force_download=False, # default
106
- )
107
- print(output_path)
108
- ```
109
-
110
- Download behavior:
111
-
112
- - accepts normal GitHub file URLs (`github.com/.../blob/...`) and raw URLs
113
- - skips download when `output_path` already exists and matches the remote `source_hash` in `vault/index.json`
114
- - set `force_download=True` to download even when the local output appears aligned
115
- - downloads the encrypted `.asc` file to a temporary location
116
- - restores files or directories automatically with `utilitz.crypto`
117
- - removes the temporary encrypted file after restore
118
-
119
- ## Password Source
120
-
121
- `upload_to_github` and `download_from_github` auto-detect password from:
122
-
123
- - `GITSTORE_PASSWORD`
124
-
125
- If `password` is not passed, the environment variable is used.
1
+ Metadata-Version: 2.4
2
+ Name: gitstore
3
+ Version: 0.2.2
4
+ Summary: Utilities to encrypt files/directories with utilitz and exchange them through GitHub repositories.
5
+ Author: artitzco
6
+ License: MIT
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: requests>=2.31.0
10
+ Requires-Dist: utilitz[crypto]
11
+
12
+ # gitstore
13
+
14
+ `gitstore` is a focused Python package for one goal:
15
+
16
+ - upload encrypted files/folders to a GitHub-backed repo
17
+ - download and restore encrypted GitHub files later
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ pip install gitstore
23
+ ```
24
+
25
+ ## Dependency on `utilitz`
26
+
27
+ This project depends on:
28
+
29
+ - `utilitz[crypto]`
30
+ - `requests`
31
+
32
+ ## Project Structure
33
+
34
+ ```text
35
+ gitstore/
36
+ src/gitstore/
37
+ __init__.py
38
+ client.py
39
+ config.py
40
+ crypto_ops.py
41
+ github_ops.py
42
+ pyproject.toml
43
+ README.md
44
+ ```
45
+
46
+ ## Core API
47
+
48
+ ```python
49
+ from gitstore import upload_to_github, restore_from_github, restore_from_file
50
+ ```
51
+
52
+ ## Upload
53
+
54
+ ```python
55
+ from gitstore import upload_to_github
56
+
57
+ record = upload_to_github(
58
+ source_path="C:/data/documento.pdf", # file or directory
59
+ name="documento_ventas_q2", # logical name only
60
+ repo_path="C:/repos/my-publish-repo", # required
61
+ password=None, # default: uses GITSTORE_PASSWORD
62
+ vault_dir="vault", # default
63
+ request_timeout=60, # default
64
+ security_level="high", # default
65
+ replace_existing=True, # default
66
+ force_upload=False, # default
67
+ commit_message=None, # default: automatic message
68
+ )
69
+ print(record)
70
+ ```
71
+
72
+ Upload behavior:
73
+
74
+ - computes `source_hash` from source content before encryption
75
+ - skips upload if same `name` already has same `source_hash`
76
+ - set `force_upload=True` to upload even when the current source matches the remote metadata
77
+ - stores artifact as `vault/<name>.asc`
78
+ - stores metadata in `vault/index.json`
79
+ - removes temporary encrypted file after processing
80
+
81
+ ## Valid Names
82
+
83
+ `name` is the logical identifier used to upload an artifact.
84
+ It is intentionally strict to keep Git paths predictable:
85
+
86
+ - allowed characters: letters, numbers, dots, underscores, and hyphens
87
+ - must start with a letter or number
88
+ - spaces and path separators are not allowed
89
+
90
+ Valid examples:
91
+
92
+ ```text
93
+ documento_ventas_q2
94
+ maindb-version-0.1
95
+ backup.2026_05
96
+ ```
97
+
98
+ Invalid examples:
99
+
100
+ ```text
101
+ maindb -version 0.1
102
+ ../secret
103
+ folder/documento
104
+ ```
105
+
106
+ ## Download
107
+
108
+ ```python
109
+ from gitstore import restore_from_github
110
+
111
+ output_path = restore_from_github(
112
+ github_raw_url="https://raw.githubusercontent.com/USER/REPO/main/vault/documento_ventas_q2.asc",
113
+ password=None, # default: uses GITSTORE_PASSWORD
114
+ output_path=None, # default: restores in the current working directory
115
+ overwrite=False, # default
116
+ force_download=False, # default
117
+ )
118
+ print(output_path)
119
+ ```
120
+
121
+ Local restore (no network):
122
+
123
+ ```python
124
+ from gitstore import restore_from_file
125
+
126
+ output_path = restore_from_file(
127
+ encrypted_file_path="C:/downloads/documento_ventas_q2.asc",
128
+ password=None, # default: uses GITSTORE_PASSWORD
129
+ output_path=None, # optional
130
+ overwrite=False, # default
131
+ )
132
+ print(output_path)
133
+ ```
134
+
135
+ Tip:
136
+
137
+ - use `restore_from_file(...)` when the target machine has SSL/certificate restrictions and you prefer manual transfer of the `.asc` file.
138
+
139
+ Download behavior:
140
+
141
+ - expects RAW GitHub URLs (`raw.githubusercontent.com/...`) as primary input
142
+ - also accepts `github.com/.../blob/...` and normalizes automatically
143
+ - skips download when `output_path` already exists and matches the remote `source_hash` in `vault/index.json`
144
+ - set `force_download=True` to download even when the local output appears aligned
145
+ - downloads the encrypted `.asc` file to a temporary location
146
+ - restores files or directories automatically with `utilitz.crypto`
147
+ - removes the temporary encrypted file after restore
148
+ - supports local decode with `restore_from_file(...)` when manual download is preferred
149
+
150
+ ## Password Source
151
+
152
+ `upload_to_github`, `restore_from_github`, and `restore_from_file` auto-detect password from:
153
+
154
+ - `GITSTORE_PASSWORD`
155
+
156
+ If `password` is not passed, the environment variable is used.
File without changes