git2svn 0.4.0__tar.gz → 0.5.0__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.
Files changed (41) hide show
  1. git2svn-0.5.0/.githooks/pre-commit +34 -0
  2. git2svn-0.5.0/.github/dependabot.yml +41 -0
  3. git2svn-0.5.0/.github/workflows/ci.yml +88 -0
  4. git2svn-0.5.0/.github/workflows/release.yml +189 -0
  5. git2svn-0.5.0/.gitignore +13 -0
  6. git2svn-0.5.0/.pre-commit-config.yaml +9 -0
  7. git2svn-0.5.0/CONTRIBUTING.md +90 -0
  8. {git2svn-0.4.0 → git2svn-0.5.0}/PKG-INFO +2 -1
  9. git2svn-0.5.0/docs/arc42/README.md +229 -0
  10. git2svn-0.5.0/docs/arc42/adrs.md +87 -0
  11. git2svn-0.5.0/docs/arc42/concepts.md +56 -0
  12. git2svn-0.5.0/docs/req42.md +108 -0
  13. git2svn-0.5.0/docs/user-guide/README.md +64 -0
  14. git2svn-0.5.0/docs/user-guide/commands.md +190 -0
  15. git2svn-0.5.0/docs/user-guide/integration-workflow.md +165 -0
  16. git2svn-0.5.0/docs/user-guide/troubleshooting.md +85 -0
  17. {git2svn-0.4.0 → git2svn-0.5.0}/git2svn/__init__.py +8 -2
  18. git2svn-0.5.0/git2svn/_version.py +24 -0
  19. {git2svn-0.4.0 → git2svn-0.5.0}/git2svn/cli.py +34 -7
  20. {git2svn-0.4.0 → git2svn-0.5.0}/git2svn/core.py +150 -2
  21. {git2svn-0.4.0 → git2svn-0.5.0}/git2svn/git.py +17 -0
  22. {git2svn-0.4.0 → git2svn-0.5.0}/git2svn/svn.py +79 -10
  23. {git2svn-0.4.0 → git2svn-0.5.0}/git2svn.egg-info/PKG-INFO +2 -1
  24. git2svn-0.5.0/git2svn.egg-info/SOURCES.txt +38 -0
  25. {git2svn-0.4.0 → git2svn-0.5.0}/git2svn.egg-info/requires.txt +1 -0
  26. git2svn-0.5.0/git2svn.egg-info/scm_file_list.json +34 -0
  27. git2svn-0.5.0/git2svn.py +14 -0
  28. {git2svn-0.4.0 → git2svn-0.5.0}/pyproject.toml +9 -2
  29. {git2svn-0.4.0 → git2svn-0.5.0}/tests/test_git2svn.py +223 -0
  30. git2svn-0.4.0/git2svn.egg-info/SOURCES.txt +0 -20
  31. {git2svn-0.4.0 → git2svn-0.5.0}/LICENSE.md +0 -0
  32. {git2svn-0.4.0 → git2svn-0.5.0}/README.md +0 -0
  33. {git2svn-0.4.0 → git2svn-0.5.0}/git2svn/__main__.py +0 -0
  34. {git2svn-0.4.0 → git2svn-0.5.0}/git2svn/eol.py +0 -0
  35. {git2svn-0.4.0 → git2svn-0.5.0}/git2svn/patcher.py +0 -0
  36. {git2svn-0.4.0 → git2svn-0.5.0}/git2svn/state.py +0 -0
  37. {git2svn-0.4.0 → git2svn-0.5.0}/git2svn.egg-info/dependency_links.txt +0 -0
  38. {git2svn-0.4.0 → git2svn-0.5.0}/git2svn.egg-info/entry_points.txt +0 -0
  39. {git2svn-0.4.0 → git2svn-0.5.0}/git2svn.egg-info/top_level.txt +0 -0
  40. {git2svn-0.4.0 → git2svn-0.5.0}/setup.cfg +0 -0
  41. {git2svn-0.4.0 → git2svn-0.5.0}/tests/test_e2e.py +0 -0
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env bash
2
+ # Git pre-commit hook to enforce code formatting and linting via ruff
3
+
4
+ set -e
5
+
6
+ # Check if currently on 'trunk' branch and ensure no merge commits are being created
7
+ CURRENT_BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || true)
8
+ if [ "$CURRENT_BRANCH" = "trunk" ]; then
9
+ if [ -f .git/MERGE_HEAD ]; then
10
+ echo "[git2svn pre-commit hook] ERROR: Merge commits are not permitted on 'trunk'." >&2
11
+ echo "[git2svn pre-commit hook] git2svn replay requires a strictly linear history." >&2
12
+ echo "[git2svn pre-commit hook] Please rebase your feature branch and use fast-forward: 'git merge --ff-only <branch>'" >&2
13
+ exit 1
14
+ fi
15
+ fi
16
+
17
+ # Check if ruff is available
18
+ if command -v ruff >/dev/null 2>&1; then
19
+ RUFF_CMD="ruff"
20
+ elif python3 -m ruff --version >/dev/null 2>&1; then
21
+ RUFF_CMD="python3 -m ruff"
22
+ else
23
+ echo "[git2svn pre-commit hook] WARNING: 'ruff' not found in PATH or python environment. Skipping formatting checks."
24
+ exit 0
25
+ fi
26
+
27
+ echo "[git2svn pre-commit hook] Checking code formatting..."
28
+ $RUFF_CMD format --check .
29
+
30
+ echo "[git2svn pre-commit hook] Checking code linting..."
31
+ $RUFF_CMD check .
32
+
33
+ echo "[git2svn pre-commit hook] All checks passed!"
34
+
@@ -0,0 +1,41 @@
1
+ version: 2
2
+ updates:
3
+ # Maintain Python dev dependencies in pyproject.toml
4
+ - package-ecosystem: "pip"
5
+ directory: "/"
6
+ schedule:
7
+ interval: "weekly"
8
+ day: "monday"
9
+ time: "08:00"
10
+ timezone: "Europe/Zurich"
11
+ open-pull-requests-limit: 5
12
+ labels:
13
+ - "dependencies"
14
+ - "python"
15
+ groups:
16
+ pip-minor-patch:
17
+ patterns:
18
+ - "*"
19
+ update-types:
20
+ - "minor"
21
+ - "patch"
22
+
23
+ # Maintain GitHub Actions dependencies
24
+ - package-ecosystem: "github-actions"
25
+ directory: "/"
26
+ schedule:
27
+ interval: "weekly"
28
+ day: "monday"
29
+ time: "08:00"
30
+ timezone: "Europe/Zurich"
31
+ open-pull-requests-limit: 5
32
+ labels:
33
+ - "dependencies"
34
+ - "github-actions"
35
+ groups:
36
+ actions-minor-patch:
37
+ patterns:
38
+ - "*"
39
+ update-types:
40
+ - "minor"
41
+ - "patch"
@@ -0,0 +1,88 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ "main" ]
6
+ pull_request:
7
+ branches: [ "main" ]
8
+
9
+ jobs:
10
+ lint-and-format:
11
+ name: Lint & Format (Ruff)
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - name: Check out repository
15
+ uses: actions/checkout@v7
16
+
17
+ - name: Set up Python
18
+ uses: actions/setup-python@v7
19
+ with:
20
+ python-version: "3.12"
21
+
22
+ - name: Install Ruff
23
+ run: pip install ruff
24
+
25
+ - name: Run Ruff Lint Checks
26
+ run: ruff check .
27
+
28
+ - name: Verify Formatting with Ruff
29
+ run: ruff format --check .
30
+
31
+ test:
32
+ name: Test on Python ${{ matrix.python-version }} (${{ matrix.os }})
33
+ runs-on: ${{ matrix.os }}
34
+ strategy:
35
+ fail-fast: false
36
+ matrix:
37
+ os: [ubuntu-latest, windows-latest, macos-latest]
38
+ python-version: ["3.11", "3.12", "3.13"]
39
+
40
+ steps:
41
+ - name: Check out repository
42
+ uses: actions/checkout@v7
43
+
44
+ - name: Set up Python ${{ matrix.python-version }}
45
+ uses: actions/setup-python@v7
46
+ with:
47
+ python-version: ${{ matrix.python-version }}
48
+
49
+ - name: Install Subversion (Linux)
50
+ if: runner.os == 'Linux'
51
+ run: |
52
+ sudo apt-get update
53
+ sudo apt-get install -y subversion git
54
+
55
+ - name: Install Subversion (macOS)
56
+ if: runner.os == 'macOS'
57
+ run: |
58
+ brew install subversion git
59
+
60
+ - name: Install Subversion (Windows)
61
+ if: runner.os == 'Windows'
62
+ run: |
63
+ choco install tortoisesvn -y --params:"/NoRestart"
64
+ # Add TortoiseSVN CLI tools to PATH if present
65
+ echo "C:\Program Files\TortoiseSVN\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
66
+
67
+ - name: Install Dependencies
68
+ run: pip install -e .[dev]
69
+
70
+ - name: Run Unit & Integration Tests (with Coverage)
71
+ if: runner.os == 'Linux' && matrix.python-version == '3.12'
72
+ run: |
73
+ coverage run -m unittest discover tests
74
+ coverage xml
75
+
76
+ - name: Run Unit & Integration Tests
77
+ if: runner.os != 'Linux' || matrix.python-version != '3.12'
78
+ run: python -m unittest discover tests
79
+
80
+ - name: Upload Coverage to Codecov
81
+ if: runner.os == 'Linux' && matrix.python-version == '3.12'
82
+ uses: codecov/codecov-action@v7
83
+ with:
84
+ token: ${{ secrets.CODECOV_TOKEN }}
85
+ files: coverage.xml
86
+ flags: unittests
87
+ fail_ci_if_error: false
88
+
@@ -0,0 +1,189 @@
1
+ name: Release Pipeline
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+ workflow_dispatch:
8
+ inputs:
9
+ bump:
10
+ description: 'Semantic Version Bump'
11
+ required: true
12
+ default: 'patch'
13
+ type: choice
14
+ options:
15
+ - patch
16
+ - minor
17
+ - major
18
+ - custom
19
+ custom_version:
20
+ description: 'Custom Version (only if "custom" selected above, e.g. v0.3.1)'
21
+ required: false
22
+ default: ''
23
+
24
+ permissions:
25
+ contents: write
26
+ id-token: write # Required for PyPI Trusted Publishing (OIDC)
27
+
28
+ jobs:
29
+ tag-release:
30
+ runs-on: ubuntu-latest
31
+ outputs:
32
+ tag: ${{ steps.resolve_tag.outputs.tag }}
33
+ steps:
34
+ - name: Checkout Code
35
+ uses: actions/checkout@v4
36
+ with:
37
+ fetch-depth: 0
38
+
39
+ - name: Resolve Release Tag
40
+ id: resolve_tag
41
+ shell: bash
42
+ run: |
43
+ if [ "${{ github.event_name }}" = "push" ]; then
44
+ TAG="${{ github.ref_name }}"
45
+ echo "Triggered by tag push: $TAG"
46
+ else
47
+ # Triggered via workflow_dispatch button -> compute next semver
48
+ LATEST_TAG=$(git tag --sort=-v:refname | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+$' | head -n 1 || true)
49
+ if [ -z "$LATEST_TAG" ]; then
50
+ LATEST_TAG="v0.3.0"
51
+ fi
52
+ echo "Latest stable tag: $LATEST_TAG"
53
+
54
+ RAW_VER="${LATEST_TAG#v}"
55
+ IFS='.' read -r MAJOR MINOR PATCH <<< "$RAW_VER"
56
+
57
+ BUMP="${{ github.event.inputs.bump }}"
58
+ CUSTOM="${{ github.event.inputs.custom_version }}"
59
+
60
+ if [ "$BUMP" = "patch" ]; then
61
+ TAG="v${MAJOR}.${MINOR}.$((PATCH + 1))"
62
+ elif [ "$BUMP" = "minor" ]; then
63
+ TAG="v${MAJOR}.$((MINOR + 1)).0"
64
+ elif [ "$BUMP" = "major" ]; then
65
+ TAG="v$((MAJOR + 1)).0.0"
66
+ elif [ "$BUMP" = "custom" ]; then
67
+ if [ -z "$CUSTOM" ]; then
68
+ echo "Error: custom_version cannot be empty when bump=custom" >&2
69
+ exit 1
70
+ fi
71
+ if [[ ! "$CUSTOM" =~ ^v ]]; then
72
+ TAG="v${CUSTOM}"
73
+ else
74
+ TAG="${CUSTOM}"
75
+ fi
76
+ fi
77
+
78
+ echo "Computed new tag: $TAG"
79
+ git config user.name "github-actions[bot]"
80
+ git config user.email "github-actions[bot]@users.noreply.github.com"
81
+ git tag -a "$TAG" -m "Release $TAG"
82
+ git push origin "$TAG"
83
+ fi
84
+
85
+ echo "tag=$TAG" >> "$GITHUB_OUTPUT"
86
+
87
+ build-and-publish:
88
+ needs: tag-release
89
+ runs-on: ubuntu-latest
90
+ steps:
91
+ - name: Checkout Code
92
+ uses: actions/checkout@v4
93
+ with:
94
+ fetch-depth: 0
95
+ ref: ${{ needs.tag-release.outputs.tag }}
96
+
97
+ - name: Fetch All Tags
98
+ run: |
99
+ git fetch --tags --force
100
+
101
+ - name: Set up Python
102
+ uses: actions/setup-python@v5
103
+ with:
104
+ python-version: '3.12'
105
+
106
+ - name: Install Build Tools
107
+ run: |
108
+ pip install build setuptools-scm
109
+
110
+ - name: Build Wheel & Sdist
111
+ env:
112
+ TAG: ${{ needs.tag-release.outputs.tag }}
113
+ run: |
114
+ export SETUPTOOLS_SCM_PRETEND_VERSION="${TAG#v}"
115
+ echo "Building package for release version: $SETUPTOOLS_SCM_PRETEND_VERSION"
116
+ python -m build
117
+
118
+ - name: Create GitHub Release
119
+ env:
120
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
121
+ TAG: ${{ needs.tag-release.outputs.tag }}
122
+ run: |
123
+ EXTRA_FLAGS=()
124
+ if [[ "$TAG" =~ (alpha|beta|rc|dev) ]]; then
125
+ EXTRA_FLAGS+=(--prerelease)
126
+ fi
127
+
128
+ START_TAG=$(git tag --sort=-v:refname | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+$' | grep -v "^${TAG}$" | head -n 1 || true)
129
+ if [ -z "$START_TAG" ]; then
130
+ START_TAG=$(git describe --tags --abbrev=0 "${TAG}^" 2>/dev/null || true)
131
+ fi
132
+
133
+ RANGE="${START_TAG}..${TAG}"
134
+ if [ -z "$START_TAG" ]; then
135
+ RANGE="${TAG}"
136
+ fi
137
+
138
+ REPO_URL="https://github.com/${{ github.repository }}"
139
+ NOTES_FILE="/tmp/release_notes.md"
140
+ echo "## What's Changed" > "$NOTES_FILE"
141
+ echo "" >> "$NOTES_FILE"
142
+
143
+ FEATS=$(git log "$RANGE" --grep="^feat" --pretty=format:"* %s ([%h]($REPO_URL/commit/%H))" || true)
144
+ FIXES=$(git log "$RANGE" --grep="^fix" --pretty=format:"* %s ([%h]($REPO_URL/commit/%H))" || true)
145
+ MAINT=$(git log "$RANGE" --grep="^chore" --grep="^perf" --grep="^refactor" --grep="^docs" --pretty=format:"* %s ([%h]($REPO_URL/commit/%H))" || true)
146
+
147
+ HAS_CONTENT=false
148
+ if [ -n "$FEATS" ]; then
149
+ echo "### 🚀 Features" >> "$NOTES_FILE"
150
+ echo "$FEATS" >> "$NOTES_FILE"
151
+ echo "" >> "$NOTES_FILE"
152
+ HAS_CONTENT=true
153
+ fi
154
+
155
+ if [ -n "$FIXES" ]; then
156
+ echo "### 🐛 Bug Fixes" >> "$NOTES_FILE"
157
+ echo "$FIXES" >> "$NOTES_FILE"
158
+ echo "" >> "$NOTES_FILE"
159
+ HAS_CONTENT=true
160
+ fi
161
+
162
+ if [ -n "$MAINT" ]; then
163
+ echo "### 🧰 Maintenance & Documentation" >> "$NOTES_FILE"
164
+ echo "$MAINT" >> "$NOTES_FILE"
165
+ echo "" >> "$NOTES_FILE"
166
+ HAS_CONTENT=true
167
+ fi
168
+
169
+ if [ "$HAS_CONTENT" = false ]; then
170
+ git log "$RANGE" --pretty=format:"* %s ([%h]($REPO_URL/commit/%H))" >> "$NOTES_FILE" || true
171
+ echo "" >> "$NOTES_FILE"
172
+ fi
173
+
174
+ if [ -n "$START_TAG" ]; then
175
+ echo "**Full Changelog**: $REPO_URL/compare/${START_TAG}...${TAG}" >> "$NOTES_FILE"
176
+ fi
177
+
178
+ gh release create "$TAG" dist/* \
179
+ --title "$TAG" \
180
+ --notes-file "$NOTES_FILE" \
181
+ "${EXTRA_FLAGS[@]}"
182
+
183
+ - name: Publish to PyPI
184
+ uses: pypa/gh-action-pypi-publish@release/v1
185
+ continue-on-error: true # Allows pipeline to succeed even before PyPI Trusted Publishing is registered
186
+ with:
187
+ packages-dir: dist/
188
+ skip-existing: true
189
+ print-hash: true
@@ -0,0 +1,13 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ .pytest_cache/
5
+ *.rej
6
+ *.orig
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ .coverage
11
+ coverage.xml
12
+ htmlcov/
13
+ git2svn/_version.py
@@ -0,0 +1,9 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.8.0
4
+ hooks:
5
+ # Run the linter
6
+ - id: ruff
7
+ args: [--fix]
8
+ # Run the formatter
9
+ - id: ruff-format
@@ -0,0 +1,90 @@
1
+ # Contributing to git2svn
2
+
3
+ Thank you for contributing to `git2svn`! This document outlines our development workflow, coding standards, and contribution guidelines.
4
+
5
+ ---
6
+
7
+ ## 1. Development Environment Setup
8
+
9
+ `git2svn` is built entirely on the Python 3 standard library with zero runtime dependencies. Only development tooling (Ruff) is required.
10
+
11
+ ### 1.1 Requirements
12
+ * Python `>= 3.11`
13
+ * `git` CLI (standard installation)
14
+ * `svn` CLI (Apache Subversion command-line client)
15
+ * `ruff` for code formatting and linting
16
+
17
+ ### 1.2 Installation for Development
18
+ ```bash
19
+ # Clone the repository
20
+ git clone https://github.com/your-org/git2svn.git
21
+ cd git2svn
22
+
23
+ # Optional: create a virtual environment
24
+ python3 -m venv .venv
25
+ source .venv/bin/activate
26
+
27
+ # Install dev dependencies (ruff)
28
+ pip install -e ".[dev]"
29
+ ```
30
+
31
+ ---
32
+
33
+ ## 2. Coding Standards & Conventions
34
+
35
+ ### 2.1 Commit Messages
36
+ All commit messages **must** strictly adhere to the [Conventional Commits](https://www.conventionalcommits.org/) specification:
37
+ ```text
38
+ <type>(<optional scope>): <description>
39
+
40
+ [optional body]
41
+
42
+ [optional footer(s)]
43
+ ```
44
+ * **Allowed Types:** `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`.
45
+ * **Example:** `feat(patch): replace patch with git apply and add EOL normalization`
46
+
47
+ ### 2.2 Code Formatting & Linting
48
+ We use [Ruff](https://astral.sh/ruff) configured in `pyproject.toml` (target Python 3.11+, line length 120):
49
+ ```bash
50
+ # Check code for lint errors and auto-fix what's safe
51
+ ruff check --fix .
52
+
53
+ # Format code
54
+ ruff format .
55
+
56
+ # Check formatting without modifying
57
+ ruff format --check .
58
+ ```
59
+ All code must pass `ruff check .` and `ruff format --check .` with zero errors or warnings before committing.
60
+
61
+ ### 2.3 Documentation-as-Code
62
+ * All architecture documentation resides in [`docs/arc42.md`](docs/arc42.md) following the [arc42 template](https://arc42.org/).
63
+ * All requirements documentation resides in [`docs/req42.md`](docs/req42.md) following the [req42 framework](https://req42.de/).
64
+ * CLI workflows and command guides reside in [`docs/user-guide.md`](docs/user-guide.md).
65
+ * Diagrams are embedded directly using **Mermaid.js** code blocks (`mermaid`).
66
+
67
+ ---
68
+
69
+ ## 3. Testing Guidelines
70
+
71
+ ### 3.1 Running Tests
72
+ Run the test suite using Python's built-in `unittest` runner:
73
+ ```bash
74
+ python3 -m unittest discover tests
75
+ ```
76
+
77
+ ### 3.2 Writing Tests
78
+ * Any new feature or bugfix must include corresponding automated tests in `tests/`.
79
+ * Mock external network or real SVN servers where appropriate, but use real temporary Git repositories and directory structures (`tempfile.TemporaryDirectory`) for unit and integration testing.
80
+ * When adding newline/patch logic, test both `\r\n` (CRLF) and `\n` (LF) scenarios to prevent regressions with SVN `E135000` mixed line endings.
81
+
82
+ ---
83
+
84
+ ## 4. Pull Request Process
85
+
86
+ 1. Create a feature branch off `main` (e.g. `feat/my-new-option`).
87
+ 2. Make your changes adhering to conventional commits.
88
+ 3. Run `ruff check .`, `ruff format --check .`, and `python3 -m unittest discover tests`.
89
+ 4. Ensure documentation in `docs/` and `README.md` is updated if CLI syntax or architecture changed.
90
+ 5. Open a Pull Request with a clear description of the problem solved.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: git2svn
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Summary: CLI utility to synchronize changes from a local Git repository to a local SVN working copy
5
5
  Author: Simon
6
6
  License: Apache-2.0
@@ -27,6 +27,7 @@ License-File: LICENSE.md
27
27
  Provides-Extra: dev
28
28
  Requires-Dist: coverage>=7.0.0; extra == "dev"
29
29
  Requires-Dist: ruff>=0.8.0; extra == "dev"
30
+ Requires-Dist: setuptools-scm>=8.0; extra == "dev"
30
31
  Dynamic: license-file
31
32
 
32
33
  # Git-to-SVN Synchronization CLI (`git2svn`)