git-notes-hooks 0.1.0__tar.gz → 0.1.6__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.
- git_notes_hooks-0.1.6/PKG-INFO +114 -0
- git_notes_hooks-0.1.6/README.md +81 -0
- git_notes_hooks-0.1.6/pyproject.toml +58 -0
- git_notes_hooks-0.1.6/tests/test_install.py +94 -0
- git_notes_hooks-0.1.0/PKG-INFO +0 -12
- git_notes_hooks-0.1.0/pyproject.toml +0 -21
- {git_notes_hooks-0.1.0 → git_notes_hooks-0.1.6}/setup.cfg +0 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: git-notes-hooks
|
|
3
|
+
Version: 0.1.6
|
|
4
|
+
Summary: Automatic Git hooks to keep refs/notes/* synchronized across all remotes on push and pull
|
|
5
|
+
Author-email: Bimo <i.s41m0011@gmail.com>
|
|
6
|
+
License: MIT OR Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/isaim0011/git-notes
|
|
8
|
+
Project-URL: Repository, https://github.com/isaim0011/git-notes
|
|
9
|
+
Project-URL: Issues, https://github.com/isaim0011/git-notes/issues
|
|
10
|
+
Project-URL: Documentation, https://github.com/isaim0011/git-notes#readme
|
|
11
|
+
Project-URL: Changelog, https://github.com/isaim0011/git-notes/blob/main/docs/CHANGELOG.md
|
|
12
|
+
Keywords: git,git-notes,git-hooks,code-review,decentralized,developer-tools
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
25
|
+
Requires-Python: >=3.11
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
Requires-Dist: click>=8.1
|
|
28
|
+
Requires-Dist: rich>=13.0
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-mock; extra == "dev"
|
|
32
|
+
Requires-Dist: ruff; extra == "dev"
|
|
33
|
+
|
|
34
|
+
# git-notes-hooks
|
|
35
|
+
|
|
36
|
+
> **Automatic Git hooks to keep `refs/notes/*` seamlessly synchronized across all remotes on every push and pull.**
|
|
37
|
+
|
|
38
|
+
[](https://pypi.org/project/git-notes-hooks/)
|
|
39
|
+
[](https://github.com/isaim0011/git-notes)
|
|
40
|
+
[](https://pypi.org/project/git-notes-hooks/)
|
|
41
|
+
|
|
42
|
+
`git-notes-hooks` provides automated git lifecycle integration for the **[git-notes](https://github.com/isaim0011/git-notes)** ecosystem. It installs zero-friction client-side git hooks into your repositories to ensure decentralized code review comments and notes travel with your commits automatically.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## ⚡ Quick Installation
|
|
47
|
+
|
|
48
|
+
Install from PyPI via pip:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pip install git-notes-hooks
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Or using pipx:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pipx install git-notes-hooks
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 🚀 Usage
|
|
63
|
+
|
|
64
|
+
Navigate to any Git repository and run:
|
|
65
|
+
|
|
66
|
+
### 1. Install Hooks
|
|
67
|
+
Install the automated push/pull synchronization hooks into `.git/hooks`:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
git-notes-hooks install
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
This installs:
|
|
74
|
+
- `post-commit`: Updates local note indices on every commit
|
|
75
|
+
- `pre-push`: Pushes `refs/notes/*` to `origin` whenever you run `git push`
|
|
76
|
+
- `post-merge`: Fetches and merges remote notes from `origin` on `git pull`
|
|
77
|
+
|
|
78
|
+
### 2. Check Hook Status
|
|
79
|
+
Verify active git-notes hooks in your current repository:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
git-notes-hooks status
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 3. Uninstall Hooks
|
|
86
|
+
Safely remove git-notes hooks at any time:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
git-notes-hooks uninstall
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## 🔒 History-Safe & Non-Destructive
|
|
95
|
+
|
|
96
|
+
`git-notes-hooks` operates strictly on Git's native note references (`refs/notes/comments`, `refs/notes/review`, `refs/notes/todos`). It **never modifies commit SHAs, git history, or working tree files**.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## 🔗 Links & Resources
|
|
101
|
+
|
|
102
|
+
- **GitHub Repository**: [https://github.com/isaim0011/git-notes](https://github.com/isaim0011/git-notes)
|
|
103
|
+
- **Issue Tracker**: [https://github.com/isaim0011/git-notes/issues](https://github.com/isaim0011/git-notes/issues)
|
|
104
|
+
- **Documentation**: [https://github.com/isaim0011/git-notes/blob/main/docs/ARCHITECTURE.md](https://github.com/isaim0011/git-notes/blob/main/docs/ARCHITECTURE.md)
|
|
105
|
+
- **Release Downloads**: [https://github.com/isaim0011/git-notes/releases](https://github.com/isaim0011/git-notes/releases)
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 📄 License
|
|
110
|
+
|
|
111
|
+
Licensed under either of:
|
|
112
|
+
- Apache License, Version 2.0
|
|
113
|
+
- MIT License
|
|
114
|
+
at your option.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# git-notes-hooks
|
|
2
|
+
|
|
3
|
+
> **Automatic Git hooks to keep `refs/notes/*` seamlessly synchronized across all remotes on every push and pull.**
|
|
4
|
+
|
|
5
|
+
[](https://pypi.org/project/git-notes-hooks/)
|
|
6
|
+
[](https://github.com/isaim0011/git-notes)
|
|
7
|
+
[](https://pypi.org/project/git-notes-hooks/)
|
|
8
|
+
|
|
9
|
+
`git-notes-hooks` provides automated git lifecycle integration for the **[git-notes](https://github.com/isaim0011/git-notes)** ecosystem. It installs zero-friction client-side git hooks into your repositories to ensure decentralized code review comments and notes travel with your commits automatically.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## ⚡ Quick Installation
|
|
14
|
+
|
|
15
|
+
Install from PyPI via pip:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install git-notes-hooks
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or using pipx:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pipx install git-notes-hooks
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 🚀 Usage
|
|
30
|
+
|
|
31
|
+
Navigate to any Git repository and run:
|
|
32
|
+
|
|
33
|
+
### 1. Install Hooks
|
|
34
|
+
Install the automated push/pull synchronization hooks into `.git/hooks`:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
git-notes-hooks install
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This installs:
|
|
41
|
+
- `post-commit`: Updates local note indices on every commit
|
|
42
|
+
- `pre-push`: Pushes `refs/notes/*` to `origin` whenever you run `git push`
|
|
43
|
+
- `post-merge`: Fetches and merges remote notes from `origin` on `git pull`
|
|
44
|
+
|
|
45
|
+
### 2. Check Hook Status
|
|
46
|
+
Verify active git-notes hooks in your current repository:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
git-notes-hooks status
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 3. Uninstall Hooks
|
|
53
|
+
Safely remove git-notes hooks at any time:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
git-notes-hooks uninstall
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 🔒 History-Safe & Non-Destructive
|
|
62
|
+
|
|
63
|
+
`git-notes-hooks` operates strictly on Git's native note references (`refs/notes/comments`, `refs/notes/review`, `refs/notes/todos`). It **never modifies commit SHAs, git history, or working tree files**.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 🔗 Links & Resources
|
|
68
|
+
|
|
69
|
+
- **GitHub Repository**: [https://github.com/isaim0011/git-notes](https://github.com/isaim0011/git-notes)
|
|
70
|
+
- **Issue Tracker**: [https://github.com/isaim0011/git-notes/issues](https://github.com/isaim0011/git-notes/issues)
|
|
71
|
+
- **Documentation**: [https://github.com/isaim0011/git-notes/blob/main/docs/ARCHITECTURE.md](https://github.com/isaim0011/git-notes/blob/main/docs/ARCHITECTURE.md)
|
|
72
|
+
- **Release Downloads**: [https://github.com/isaim0011/git-notes/releases](https://github.com/isaim0011/git-notes/releases)
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 📄 License
|
|
77
|
+
|
|
78
|
+
Licensed under either of:
|
|
79
|
+
- Apache License, Version 2.0
|
|
80
|
+
- MIT License
|
|
81
|
+
at your option.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "git-notes-hooks"
|
|
7
|
+
version = "0.1.6"
|
|
8
|
+
description = "Automatic Git hooks to keep refs/notes/* synchronized across all remotes on push and pull"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = { text = "MIT OR Apache-2.0" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Bimo", email = "i.s41m0011@gmail.com" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["git", "git-notes", "git-hooks", "code-review", "decentralized", "developer-tools"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"License :: OSI Approved :: Apache Software License",
|
|
22
|
+
"Operating System :: OS Independent",
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
"Programming Language :: Python :: 3.14",
|
|
28
|
+
"Topic :: Software Development :: Version Control :: Git",
|
|
29
|
+
]
|
|
30
|
+
dependencies = [
|
|
31
|
+
"click>=8.1",
|
|
32
|
+
"rich>=13.0",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[project.urls]
|
|
36
|
+
Homepage = "https://github.com/isaim0011/git-notes"
|
|
37
|
+
Repository = "https://github.com/isaim0011/git-notes"
|
|
38
|
+
Issues = "https://github.com/isaim0011/git-notes/issues"
|
|
39
|
+
Documentation = "https://github.com/isaim0011/git-notes#readme"
|
|
40
|
+
Changelog = "https://github.com/isaim0011/git-notes/blob/main/docs/CHANGELOG.md"
|
|
41
|
+
|
|
42
|
+
[project.scripts]
|
|
43
|
+
git-notes-hooks = "gn_hooks.cli:main"
|
|
44
|
+
|
|
45
|
+
[project.optional-dependencies]
|
|
46
|
+
dev = [
|
|
47
|
+
"pytest>=8",
|
|
48
|
+
"pytest-mock",
|
|
49
|
+
"ruff",
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
[tool.setuptools.packages.find]
|
|
53
|
+
where = [".."]
|
|
54
|
+
include = ["gn_hooks*"]
|
|
55
|
+
|
|
56
|
+
[tool.pytest.ini_options]
|
|
57
|
+
pythonpath = ["."]
|
|
58
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from gn_hooks.install import find_git_root
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_find_git_root_at_repo_root(tmp_path: Path):
|
|
8
|
+
"""find_git_root returns the path itself when .git dir is directly in path."""
|
|
9
|
+
git_dir = tmp_path / ".git"
|
|
10
|
+
git_dir.mkdir()
|
|
11
|
+
|
|
12
|
+
result = find_git_root(tmp_path)
|
|
13
|
+
assert result == tmp_path.resolve()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_find_git_root_from_nested_subdir(tmp_path: Path):
|
|
17
|
+
"""find_git_root walks up directory tree from a nested subdirectory to find .git dir."""
|
|
18
|
+
git_dir = tmp_path / ".git"
|
|
19
|
+
git_dir.mkdir()
|
|
20
|
+
|
|
21
|
+
nested_dir = tmp_path / "sub1" / "sub2" / "sub3"
|
|
22
|
+
nested_dir.mkdir(parents=True)
|
|
23
|
+
|
|
24
|
+
result = find_git_root(nested_dir)
|
|
25
|
+
assert result == tmp_path.resolve()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def test_find_git_root_from_file_path(tmp_path: Path):
|
|
29
|
+
"""find_git_root works when passed a file path inside a repository."""
|
|
30
|
+
git_dir = tmp_path / ".git"
|
|
31
|
+
git_dir.mkdir()
|
|
32
|
+
|
|
33
|
+
sub_dir = tmp_path / "src"
|
|
34
|
+
sub_dir.mkdir()
|
|
35
|
+
file_path = sub_dir / "main.py"
|
|
36
|
+
file_path.write_text("print('hello')")
|
|
37
|
+
|
|
38
|
+
result = find_git_root(file_path)
|
|
39
|
+
assert result == tmp_path.resolve()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_find_git_root_with_relative_path(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
|
|
43
|
+
"""find_git_root handles relative paths correctly by resolving them."""
|
|
44
|
+
git_dir = tmp_path / ".git"
|
|
45
|
+
git_dir.mkdir()
|
|
46
|
+
|
|
47
|
+
sub_dir = tmp_path / "sub"
|
|
48
|
+
sub_dir.mkdir()
|
|
49
|
+
|
|
50
|
+
monkeypatch.chdir(sub_dir)
|
|
51
|
+
result = find_git_root(Path("."))
|
|
52
|
+
assert result == tmp_path.resolve()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_find_git_root_when_git_is_a_file(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
|
|
56
|
+
"""find_git_root ignores .git if it is a file instead of a directory."""
|
|
57
|
+
resolved_tmp = tmp_path.resolve()
|
|
58
|
+
sub_dir = resolved_tmp / "sub"
|
|
59
|
+
sub_dir.mkdir()
|
|
60
|
+
git_file = sub_dir / ".git"
|
|
61
|
+
git_file.write_text("gitdir: /path/to/git")
|
|
62
|
+
|
|
63
|
+
# Stop search loop at resolved_tmp to isolate test from outer directory tree
|
|
64
|
+
original_parent_fget = Path.parent.fget
|
|
65
|
+
|
|
66
|
+
def custom_parent(self):
|
|
67
|
+
if self == resolved_tmp:
|
|
68
|
+
return self
|
|
69
|
+
return original_parent_fget(self)
|
|
70
|
+
|
|
71
|
+
monkeypatch.setattr(Path, "parent", property(custom_parent))
|
|
72
|
+
|
|
73
|
+
with pytest.raises(FileNotFoundError, match="Not a git repository"):
|
|
74
|
+
find_git_root(sub_dir)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def test_find_git_root_not_found_raises_file_not_found_error(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
|
|
78
|
+
"""find_git_root raises FileNotFoundError when no parent directory contains a .git directory."""
|
|
79
|
+
resolved_tmp = tmp_path.resolve()
|
|
80
|
+
no_git_dir = resolved_tmp / "no_git_dir"
|
|
81
|
+
no_git_dir.mkdir()
|
|
82
|
+
|
|
83
|
+
# Stop search loop at resolved_tmp to guarantee clean test isolation
|
|
84
|
+
original_parent_fget = Path.parent.fget
|
|
85
|
+
|
|
86
|
+
def custom_parent(self):
|
|
87
|
+
if self == resolved_tmp:
|
|
88
|
+
return self
|
|
89
|
+
return original_parent_fget(self)
|
|
90
|
+
|
|
91
|
+
monkeypatch.setattr(Path, "parent", property(custom_parent))
|
|
92
|
+
|
|
93
|
+
with pytest.raises(FileNotFoundError, match="Not a git repository"):
|
|
94
|
+
find_git_root(no_git_dir)
|
git_notes_hooks-0.1.0/PKG-INFO
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: git-notes-hooks
|
|
3
|
-
Version: 0.1.0
|
|
4
|
-
Summary: Auto-install git hooks that sync refs/notes/* on push/pull
|
|
5
|
-
License: MIT OR Apache-2.0
|
|
6
|
-
Requires-Python: >=3.11
|
|
7
|
-
Requires-Dist: click>=8.1
|
|
8
|
-
Requires-Dist: rich>=13.0
|
|
9
|
-
Provides-Extra: dev
|
|
10
|
-
Requires-Dist: pytest>=8; extra == "dev"
|
|
11
|
-
Requires-Dist: pytest-mock; extra == "dev"
|
|
12
|
-
Requires-Dist: ruff; extra == "dev"
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
[build-system]
|
|
2
|
-
requires = ["setuptools>=68", "wheel"]
|
|
3
|
-
build-backend = "setuptools.build_meta"
|
|
4
|
-
|
|
5
|
-
[project]
|
|
6
|
-
name = "git-notes-hooks"
|
|
7
|
-
version = "0.1.0"
|
|
8
|
-
description = "Auto-install git hooks that sync refs/notes/* on push/pull"
|
|
9
|
-
license = { text = "MIT OR Apache-2.0" }
|
|
10
|
-
requires-python = ">=3.11"
|
|
11
|
-
dependencies = ["click>=8.1", "rich>=13.0"]
|
|
12
|
-
|
|
13
|
-
[project.scripts]
|
|
14
|
-
git-notes-hooks = "gn_hooks.cli:main"
|
|
15
|
-
|
|
16
|
-
[project.optional-dependencies]
|
|
17
|
-
dev = ["pytest>=8", "pytest-mock", "ruff"]
|
|
18
|
-
|
|
19
|
-
[tool.setuptools.packages.find]
|
|
20
|
-
where = [".."]
|
|
21
|
-
include = ["gn_hooks*"]
|
|
File without changes
|