patchshuttle 0.1.0a2__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.
- patchshuttle-0.1.0a2/.github/workflows/ci.yml +83 -0
- patchshuttle-0.1.0a2/.github/workflows/release.yml +83 -0
- patchshuttle-0.1.0a2/.github/workflows/testpypi.yml +74 -0
- patchshuttle-0.1.0a2/.gitignore +30 -0
- patchshuttle-0.1.0a2/CHANGELOG.md +55 -0
- patchshuttle-0.1.0a2/LICENSE +21 -0
- patchshuttle-0.1.0a2/PKG-INFO +535 -0
- patchshuttle-0.1.0a2/README.md +501 -0
- patchshuttle-0.1.0a2/SECURITY.md +31 -0
- patchshuttle-0.1.0a2/SPEC_V0_1.md +1589 -0
- patchshuttle-0.1.0a2/docs/RELEASE.md +101 -0
- patchshuttle-0.1.0a2/pyproject.toml +93 -0
- patchshuttle-0.1.0a2/src/patchshuttle/__init__.py +98 -0
- patchshuttle-0.1.0a2/src/patchshuttle/_diff.py +317 -0
- patchshuttle-0.1.0a2/src/patchshuttle/_process.py +198 -0
- patchshuttle-0.1.0a2/src/patchshuttle/_version.py +3 -0
- patchshuttle-0.1.0a2/src/patchshuttle/actions/__init__.py +80 -0
- patchshuttle-0.1.0a2/src/patchshuttle/actions/constructors.py +211 -0
- patchshuttle-0.1.0a2/src/patchshuttle/actions/create.py +155 -0
- patchshuttle-0.1.0a2/src/patchshuttle/actions/modify.py +174 -0
- patchshuttle-0.1.0a2/src/patchshuttle/audit.py +588 -0
- patchshuttle-0.1.0a2/src/patchshuttle/backup.py +712 -0
- patchshuttle-0.1.0a2/src/patchshuttle/checks/__init__.py +37 -0
- patchshuttle-0.1.0a2/src/patchshuttle/checks/constructors.py +67 -0
- patchshuttle-0.1.0a2/src/patchshuttle/checks/runner.py +233 -0
- patchshuttle-0.1.0a2/src/patchshuttle/cli.py +766 -0
- patchshuttle-0.1.0a2/src/patchshuttle/config.py +247 -0
- patchshuttle-0.1.0a2/src/patchshuttle/context.py +370 -0
- patchshuttle-0.1.0a2/src/patchshuttle/errors.py +291 -0
- patchshuttle-0.1.0a2/src/patchshuttle/execution.py +651 -0
- patchshuttle-0.1.0a2/src/patchshuttle/formatters/__init__.py +25 -0
- patchshuttle-0.1.0a2/src/patchshuttle/formatters/runner.py +240 -0
- patchshuttle-0.1.0a2/src/patchshuttle/identifiers.py +20 -0
- patchshuttle-0.1.0a2/src/patchshuttle/inventory.py +331 -0
- patchshuttle-0.1.0a2/src/patchshuttle/logging.py +741 -0
- patchshuttle-0.1.0a2/src/patchshuttle/models.py +496 -0
- patchshuttle-0.1.0a2/src/patchshuttle/operations.py +292 -0
- patchshuttle-0.1.0a2/src/patchshuttle/parser.py +243 -0
- patchshuttle-0.1.0a2/src/patchshuttle/planner.py +1144 -0
- patchshuttle-0.1.0a2/src/patchshuttle/policy.py +377 -0
- patchshuttle-0.1.0a2/src/patchshuttle/py.typed +1 -0
- patchshuttle-0.1.0a2/src/patchshuttle/registry.py +275 -0
- patchshuttle-0.1.0a2/src/patchshuttle/resources/AI_GUIDE.md +163 -0
- patchshuttle-0.1.0a2/src/patchshuttle/resources/AUDIT-EXAMPLE.psh.yaml +10 -0
- patchshuttle-0.1.0a2/src/patchshuttle/resources/PATCH-EXAMPLE.psh.yaml +17 -0
- patchshuttle-0.1.0a2/src/patchshuttle/resources/PATCHSHUTTLE_PROTOCOL.md +109 -0
- patchshuttle-0.1.0a2/src/patchshuttle/resources/__init__.py +1 -0
- patchshuttle-0.1.0a2/src/patchshuttle/rollback.py +306 -0
- patchshuttle-0.1.0a2/src/patchshuttle/runner.py +880 -0
- patchshuttle-0.1.0a2/src/patchshuttle/verification.py +107 -0
- patchshuttle-0.1.0a2/src/patchshuttle/workspace.py +382 -0
- patchshuttle-0.1.0a2/tests/e2e/test_cli_project_cycle.py +157 -0
- patchshuttle-0.1.0a2/tests/integration/test_workflows.py +207 -0
- patchshuttle-0.1.0a2/tests/unit/test_actions.py +251 -0
- patchshuttle-0.1.0a2/tests/unit/test_audit_verify_execution.py +704 -0
- patchshuttle-0.1.0a2/tests/unit/test_backup.py +356 -0
- patchshuttle-0.1.0a2/tests/unit/test_change_transaction.py +738 -0
- patchshuttle-0.1.0a2/tests/unit/test_check_transaction.py +247 -0
- patchshuttle-0.1.0a2/tests/unit/test_checks.py +515 -0
- patchshuttle-0.1.0a2/tests/unit/test_cli.py +977 -0
- patchshuttle-0.1.0a2/tests/unit/test_config.py +206 -0
- patchshuttle-0.1.0a2/tests/unit/test_context_and_constructors.py +404 -0
- patchshuttle-0.1.0a2/tests/unit/test_diff.py +215 -0
- patchshuttle-0.1.0a2/tests/unit/test_execution.py +148 -0
- patchshuttle-0.1.0a2/tests/unit/test_formatters.py +321 -0
- patchshuttle-0.1.0a2/tests/unit/test_formatting_transaction.py +457 -0
- patchshuttle-0.1.0a2/tests/unit/test_identifiers.py +25 -0
- patchshuttle-0.1.0a2/tests/unit/test_inventory.py +380 -0
- patchshuttle-0.1.0a2/tests/unit/test_inventory_transaction.py +197 -0
- patchshuttle-0.1.0a2/tests/unit/test_logging.py +375 -0
- patchshuttle-0.1.0a2/tests/unit/test_manual_rollback.py +850 -0
- patchshuttle-0.1.0a2/tests/unit/test_models.py +517 -0
- patchshuttle-0.1.0a2/tests/unit/test_modify_actions.py +226 -0
- patchshuttle-0.1.0a2/tests/unit/test_operational_execution.py +545 -0
- patchshuttle-0.1.0a2/tests/unit/test_package.py +77 -0
- patchshuttle-0.1.0a2/tests/unit/test_parser.py +423 -0
- patchshuttle-0.1.0a2/tests/unit/test_phase19_cli.py +181 -0
- patchshuttle-0.1.0a2/tests/unit/test_planner.py +1505 -0
- patchshuttle-0.1.0a2/tests/unit/test_policy.py +558 -0
- patchshuttle-0.1.0a2/tests/unit/test_registry.py +282 -0
- patchshuttle-0.1.0a2/tests/unit/test_release_configuration.py +86 -0
- patchshuttle-0.1.0a2/tests/unit/test_rollback.py +273 -0
- patchshuttle-0.1.0a2/tests/unit/test_runner.py +897 -0
- patchshuttle-0.1.0a2/tests/unit/test_workspace.py +542 -0
- patchshuttle-0.1.0a2/tools/check_tag.py +38 -0
- patchshuttle-0.1.0a2/tools/index_smoke.py +170 -0
- patchshuttle-0.1.0a2/tools/release_checks.py +169 -0
- patchshuttle-0.1.0a2/tools/wheel_smoke.py +149 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
"on":
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
test:
|
|
17
|
+
name: ${{ matrix.os }} / Python ${{ matrix.python-version }}
|
|
18
|
+
runs-on: ${{ matrix.os }}
|
|
19
|
+
timeout-minutes: 20
|
|
20
|
+
strategy:
|
|
21
|
+
fail-fast: false
|
|
22
|
+
matrix:
|
|
23
|
+
include:
|
|
24
|
+
- os: ubuntu-24.04
|
|
25
|
+
python-version: "3.10"
|
|
26
|
+
- os: ubuntu-24.04
|
|
27
|
+
python-version: "3.12"
|
|
28
|
+
- os: ubuntu-24.04
|
|
29
|
+
python-version: "3.14"
|
|
30
|
+
- os: windows-2025
|
|
31
|
+
python-version: "3.12"
|
|
32
|
+
- os: windows-2025
|
|
33
|
+
python-version: "3.14"
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/checkout@v7.0.1
|
|
36
|
+
- uses: actions/setup-python@v7.0.0
|
|
37
|
+
with:
|
|
38
|
+
python-version: ${{ matrix.python-version }}
|
|
39
|
+
cache: pip
|
|
40
|
+
cache-dependency-path: pyproject.toml
|
|
41
|
+
- name: Install development environment
|
|
42
|
+
run: |
|
|
43
|
+
python -m pip install --upgrade pip
|
|
44
|
+
python -m pip install -e ".[dev]"
|
|
45
|
+
- name: Check import ordering
|
|
46
|
+
run: python -m isort --check-only src tests tools
|
|
47
|
+
- name: Check formatting
|
|
48
|
+
run: python -m black --check src tests tools
|
|
49
|
+
- name: Run tests with branch coverage
|
|
50
|
+
run: |
|
|
51
|
+
python -m coverage erase
|
|
52
|
+
python -m coverage run -m pytest -q
|
|
53
|
+
python -m coverage report --fail-under=100
|
|
54
|
+
|
|
55
|
+
package:
|
|
56
|
+
name: Build and smoke-test distributions
|
|
57
|
+
needs: test
|
|
58
|
+
runs-on: ubuntu-24.04
|
|
59
|
+
timeout-minutes: 20
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/checkout@v7.0.1
|
|
62
|
+
- uses: actions/setup-python@v7.0.0
|
|
63
|
+
with:
|
|
64
|
+
python-version: "3.12"
|
|
65
|
+
cache: pip
|
|
66
|
+
cache-dependency-path: pyproject.toml
|
|
67
|
+
- name: Build distributions
|
|
68
|
+
run: |
|
|
69
|
+
python -m pip install --upgrade pip
|
|
70
|
+
python -m pip install build twine
|
|
71
|
+
python -m build
|
|
72
|
+
python -m twine check dist/*
|
|
73
|
+
python tools/release_checks.py dist
|
|
74
|
+
- name: Smoke-test wheel
|
|
75
|
+
run: >-
|
|
76
|
+
python tools/wheel_smoke.py dist/*.whl
|
|
77
|
+
--version "$(python -c 'from pathlib import Path; from tools.check_tag import source_version; print(source_version(Path.cwd()))')"
|
|
78
|
+
- uses: actions/upload-artifact@v7.0.1
|
|
79
|
+
with:
|
|
80
|
+
name: patchshuttle-distributions
|
|
81
|
+
path: dist/*
|
|
82
|
+
if-no-files-found: error
|
|
83
|
+
retention-days: 14
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
name: Release to PyPI
|
|
2
|
+
|
|
3
|
+
"on":
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-24.04
|
|
13
|
+
timeout-minutes: 25
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v7.0.1
|
|
16
|
+
with:
|
|
17
|
+
ref: ${{ github.event.release.tag_name }}
|
|
18
|
+
- uses: actions/setup-python@v7.0.0
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.12"
|
|
21
|
+
cache: pip
|
|
22
|
+
cache-dependency-path: pyproject.toml
|
|
23
|
+
- name: Require tag and source version to match
|
|
24
|
+
env:
|
|
25
|
+
RELEASE_TAG: ${{ github.event.release.tag_name }}
|
|
26
|
+
run: python tools/check_tag.py "$RELEASE_TAG"
|
|
27
|
+
- name: Test, build, and validate distributions
|
|
28
|
+
run: |
|
|
29
|
+
python -m pip install --upgrade pip
|
|
30
|
+
python -m pip install -e ".[dev]"
|
|
31
|
+
python -m isort --check-only src tests tools
|
|
32
|
+
python -m black --check src tests tools
|
|
33
|
+
python -m coverage erase
|
|
34
|
+
python -m coverage run -m pytest -q
|
|
35
|
+
python -m coverage report --fail-under=100
|
|
36
|
+
python -m build
|
|
37
|
+
python -m twine check dist/*
|
|
38
|
+
python tools/release_checks.py dist
|
|
39
|
+
- name: Smoke-test wheel
|
|
40
|
+
env:
|
|
41
|
+
RELEASE_VERSION: ${{ github.event.release.tag_name }}
|
|
42
|
+
run: >-
|
|
43
|
+
python tools/wheel_smoke.py dist/*.whl
|
|
44
|
+
--version "${RELEASE_VERSION#v}"
|
|
45
|
+
- uses: actions/upload-artifact@v7.0.1
|
|
46
|
+
with:
|
|
47
|
+
name: patchshuttle-release-distributions
|
|
48
|
+
path: |
|
|
49
|
+
dist/*.whl
|
|
50
|
+
dist/*.tar.gz
|
|
51
|
+
if-no-files-found: error
|
|
52
|
+
retention-days: 30
|
|
53
|
+
|
|
54
|
+
publish:
|
|
55
|
+
needs: build
|
|
56
|
+
runs-on: ubuntu-24.04
|
|
57
|
+
timeout-minutes: 10
|
|
58
|
+
environment: pypi
|
|
59
|
+
permissions:
|
|
60
|
+
contents: read
|
|
61
|
+
id-token: write
|
|
62
|
+
steps:
|
|
63
|
+
- uses: actions/download-artifact@v8.0.1
|
|
64
|
+
with:
|
|
65
|
+
name: patchshuttle-release-distributions
|
|
66
|
+
path: dist
|
|
67
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
68
|
+
|
|
69
|
+
verify:
|
|
70
|
+
needs: publish
|
|
71
|
+
runs-on: ubuntu-24.04
|
|
72
|
+
timeout-minutes: 10
|
|
73
|
+
steps:
|
|
74
|
+
- uses: actions/checkout@v7.0.1
|
|
75
|
+
with:
|
|
76
|
+
ref: ${{ github.event.release.tag_name }}
|
|
77
|
+
- uses: actions/setup-python@v7.0.0
|
|
78
|
+
with:
|
|
79
|
+
python-version: "3.12"
|
|
80
|
+
- name: Install exact PyPI release and run smoke test
|
|
81
|
+
env:
|
|
82
|
+
RELEASE_VERSION: ${{ github.event.release.tag_name }}
|
|
83
|
+
run: python tools/index_smoke.py pypi --version "${RELEASE_VERSION#v}"
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
name: Publish to TestPyPI
|
|
2
|
+
|
|
3
|
+
"on":
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
runs-on: ubuntu-24.04
|
|
12
|
+
timeout-minutes: 20
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v7.0.1
|
|
15
|
+
- uses: actions/setup-python@v7.0.0
|
|
16
|
+
with:
|
|
17
|
+
python-version: "3.12"
|
|
18
|
+
cache: pip
|
|
19
|
+
cache-dependency-path: pyproject.toml
|
|
20
|
+
- name: Build and validate distributions
|
|
21
|
+
run: |
|
|
22
|
+
python -m pip install --upgrade pip
|
|
23
|
+
python -m pip install -e ".[dev]"
|
|
24
|
+
python -m isort --check-only src tests tools
|
|
25
|
+
python -m black --check src tests tools
|
|
26
|
+
python -m coverage erase
|
|
27
|
+
python -m coverage run -m pytest -q
|
|
28
|
+
python -m coverage report --fail-under=100
|
|
29
|
+
python -m build
|
|
30
|
+
python -m twine check dist/*
|
|
31
|
+
python tools/release_checks.py dist
|
|
32
|
+
- name: Smoke-test wheel
|
|
33
|
+
run: >-
|
|
34
|
+
python tools/wheel_smoke.py dist/*.whl
|
|
35
|
+
--version "$(python -c 'from pathlib import Path; from tools.check_tag import source_version; print(source_version(Path.cwd()))')"
|
|
36
|
+
- uses: actions/upload-artifact@v7.0.1
|
|
37
|
+
with:
|
|
38
|
+
name: patchshuttle-testpypi-distributions
|
|
39
|
+
path: |
|
|
40
|
+
dist/*.whl
|
|
41
|
+
dist/*.tar.gz
|
|
42
|
+
if-no-files-found: error
|
|
43
|
+
retention-days: 14
|
|
44
|
+
|
|
45
|
+
publish:
|
|
46
|
+
needs: build
|
|
47
|
+
runs-on: ubuntu-24.04
|
|
48
|
+
timeout-minutes: 10
|
|
49
|
+
environment: testpypi
|
|
50
|
+
permissions:
|
|
51
|
+
contents: read
|
|
52
|
+
id-token: write
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/download-artifact@v8.0.1
|
|
55
|
+
with:
|
|
56
|
+
name: patchshuttle-testpypi-distributions
|
|
57
|
+
path: dist
|
|
58
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
59
|
+
with:
|
|
60
|
+
repository-url: https://test.pypi.org/legacy/
|
|
61
|
+
|
|
62
|
+
verify:
|
|
63
|
+
needs: publish
|
|
64
|
+
runs-on: ubuntu-24.04
|
|
65
|
+
timeout-minutes: 10
|
|
66
|
+
steps:
|
|
67
|
+
- uses: actions/checkout@v7.0.1
|
|
68
|
+
- uses: actions/setup-python@v7.0.0
|
|
69
|
+
with:
|
|
70
|
+
python-version: "3.12"
|
|
71
|
+
- name: Install exact TestPyPI release and run smoke test
|
|
72
|
+
run: >-
|
|
73
|
+
python tools/index_smoke.py testpypi
|
|
74
|
+
--version "$(python -c 'from pathlib import Path; from tools.check_tag import source_version; print(source_version(Path.cwd()))')"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Python bytecode and caches
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
.pytest_cache/
|
|
5
|
+
.mypy_cache/
|
|
6
|
+
.ruff_cache/
|
|
7
|
+
.coverage
|
|
8
|
+
htmlcov/
|
|
9
|
+
|
|
10
|
+
# Virtual environments
|
|
11
|
+
.venv/
|
|
12
|
+
venv/
|
|
13
|
+
|
|
14
|
+
# Build output
|
|
15
|
+
build/
|
|
16
|
+
dist/
|
|
17
|
+
*.egg-info/
|
|
18
|
+
|
|
19
|
+
# Editors and operating systems
|
|
20
|
+
.idea/
|
|
21
|
+
.vscode/
|
|
22
|
+
.DS_Store
|
|
23
|
+
Thumbs.db
|
|
24
|
+
|
|
25
|
+
# PatchShuttle runtime data generated while developing PatchShuttle itself
|
|
26
|
+
patches/applied/
|
|
27
|
+
patches/backups/
|
|
28
|
+
patches/failed/
|
|
29
|
+
patches/logs/
|
|
30
|
+
patches/state/
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to PatchShuttle are recorded in this file. The project
|
|
4
|
+
uses semantic versioning, including Python-compatible pre-release versions.
|
|
5
|
+
|
|
6
|
+
## 0.1.0a2 - 2026-08-13
|
|
7
|
+
|
|
8
|
+
First release candidate prepared for external CI and TestPyPI qualification.
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Existing-project and empty-directory initialization with stable project IDs.
|
|
13
|
+
- Protocol 1 YAML jobs and equivalent immutable Python constructors.
|
|
14
|
+
- Bounded `audit`, transactional `patch`, and one-pass `verify` workflows.
|
|
15
|
+
- All v0.1 text actions, controlled Python, pytest, unittest, Django, import,
|
|
16
|
+
and locally configured checks.
|
|
17
|
+
- Per-job backups, automatic rollback, guarded manual rollback, and explicit
|
|
18
|
+
`--keep-changes` failure handling.
|
|
19
|
+
- Changed-Python-only isort followed by Black, with final check reruns.
|
|
20
|
+
- Workspace inventory comparison and unexpected side-effect reporting.
|
|
21
|
+
- Fixed-section timestamped logs, exact job archives, registry idempotency,
|
|
22
|
+
project snapshots, and compact AI handoffs.
|
|
23
|
+
- Integration, end-to-end, wheel smoke, release validation, and index smoke
|
|
24
|
+
tests.
|
|
25
|
+
- GitHub Actions workflows for the required Ubuntu and Windows matrix and for
|
|
26
|
+
Trusted Publishing to TestPyPI and PyPI.
|
|
27
|
+
|
|
28
|
+
### Security
|
|
29
|
+
|
|
30
|
+
- Deny-by-default confirmation for patch and verify execution.
|
|
31
|
+
- Protected and ignored path policy, symbolic-link and special-file rejection,
|
|
32
|
+
bounded inputs and outputs, non-shell subprocess execution, and best-effort
|
|
33
|
+
log redaction.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- Python 3.10 TOML compatibility in package and index-smoke checks.
|
|
38
|
+
- Windows inventory capture when path metadata does not expose stable inode
|
|
39
|
+
identifiers.
|
|
40
|
+
- Persistent cross-platform workspace locking with `filelock` native locks.
|
|
41
|
+
- Platform-neutral subprocess newlines and portable filesystem test fixtures.
|
|
42
|
+
|
|
43
|
+
### Qualification status
|
|
44
|
+
|
|
45
|
+
- Local Linux/Python 3.10 and 3.12 verification is complete with 100% statement
|
|
46
|
+
and branch coverage.
|
|
47
|
+
- The required GitHub-hosted Ubuntu/Python 3.10, 3.12, and 3.14 plus
|
|
48
|
+
Windows/Python 3.12 and 3.14 matrix passed on 2026-08-16.
|
|
49
|
+
- TestPyPI installation remains the next external release gate.
|
|
50
|
+
|
|
51
|
+
## 0.1.0a1 - 2026-08-06
|
|
52
|
+
|
|
53
|
+
Internal development checkpoint containing the initial package scaffold,
|
|
54
|
+
typed job model, validation, workspace, path policy, planner, and early
|
|
55
|
+
transaction engine. It was not published as a supported release.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PatchShuttle contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|