git-ssh-sync 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.
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/PKG-INFO +1 -1
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/pyproject.toml +1 -1
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/src/git_ssh_sync/__init__.py +1 -1
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/src/git_ssh_sync/config.py +1 -1
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/src/git_ssh_sync/git.py +2 -1
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/src/git_ssh_sync/sync.py +87 -7
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/README.md +0 -0
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/src/git_ssh_sync/attach.py +0 -0
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/src/git_ssh_sync/branch.py +0 -0
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/src/git_ssh_sync/cli.py +0 -0
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/src/git_ssh_sync/clone.py +0 -0
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/src/git_ssh_sync/console.py +0 -0
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/src/git_ssh_sync/dev.py +0 -0
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/src/git_ssh_sync/doctor.py +0 -0
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/src/git_ssh_sync/errors.py +0 -0
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/src/git_ssh_sync/logging_config.py +0 -0
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/src/git_ssh_sync/ssh.py +0 -0
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/src/git_ssh_sync/status.py +0 -0
- {git_ssh_sync-0.4.0 → git_ssh_sync-0.5.0}/src/git_ssh_sync/windows_git_ssh.py +0 -0
|
@@ -109,7 +109,7 @@ def default_config_path() -> Path:
|
|
|
109
109
|
if sys.platform == "win32":
|
|
110
110
|
base = Path(os.environ.get("APPDATA", Path.home() / "AppData" / "Roaming"))
|
|
111
111
|
else:
|
|
112
|
-
base = Path.home() / ".config"
|
|
112
|
+
base = Path(os.environ.get("XDG_CONFIG_HOME", Path.home() / ".config"))
|
|
113
113
|
return base / "git-ssh-sync" / "config.yaml"
|
|
114
114
|
|
|
115
115
|
|
|
@@ -197,6 +197,7 @@ def remote(
|
|
|
197
197
|
cwd: str | Path | None = None,
|
|
198
198
|
env: Mapping[str, str] | None = None,
|
|
199
199
|
verbose: bool = False,
|
|
200
|
+
check: bool = True,
|
|
200
201
|
) -> CommandResult:
|
|
201
202
|
"""Run `git remote`."""
|
|
202
|
-
return run_git(["remote", *args], cwd=cwd, env=env, verbose=verbose)
|
|
203
|
+
return run_git(["remote", *args], cwd=cwd, env=env, verbose=verbose, check=check)
|
|
@@ -90,6 +90,31 @@ def _ensure_origin_branch(local_path: Path, branch: str) -> None:
|
|
|
90
90
|
)
|
|
91
91
|
|
|
92
92
|
|
|
93
|
+
def _origin_branch_exists_on_remote(local_path: Path, branch: str) -> bool:
|
|
94
|
+
result = git.run_git(
|
|
95
|
+
["ls-remote", "--exit-code", "--heads", "origin", branch],
|
|
96
|
+
cwd=local_path,
|
|
97
|
+
check=False,
|
|
98
|
+
)
|
|
99
|
+
if result.returncode == 0:
|
|
100
|
+
return True
|
|
101
|
+
if result.returncode == 2:
|
|
102
|
+
return False
|
|
103
|
+
raise CommandExecutionError(
|
|
104
|
+
environment=result.environment,
|
|
105
|
+
command=result.command,
|
|
106
|
+
returncode=result.returncode,
|
|
107
|
+
cwd=result.cwd,
|
|
108
|
+
stdout=result.stdout,
|
|
109
|
+
stderr=result.stderr,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _ensure_origin_branch_on_remote(local_path: Path, branch: str) -> None:
|
|
114
|
+
if not _origin_branch_exists_on_remote(local_path, branch):
|
|
115
|
+
raise SyncError(f"Origin branch does not exist: {branch}")
|
|
116
|
+
|
|
117
|
+
|
|
93
118
|
def _ensure_origin_branch_missing(project: str, local_path: Path, branch: str) -> None:
|
|
94
119
|
if _origin_branch_exists(local_path, branch):
|
|
95
120
|
raise SyncError(
|
|
@@ -99,6 +124,17 @@ def _ensure_origin_branch_missing(project: str, local_path: Path, branch: str) -
|
|
|
99
124
|
)
|
|
100
125
|
|
|
101
126
|
|
|
127
|
+
def _ensure_origin_branch_missing_on_remote(
|
|
128
|
+
project: str, local_path: Path, branch: str
|
|
129
|
+
) -> None:
|
|
130
|
+
if _origin_branch_exists_on_remote(local_path, branch):
|
|
131
|
+
raise SyncError(
|
|
132
|
+
f"Origin branch already exists: {branch}\n\n"
|
|
133
|
+
"Run checkout without --base to use the existing branch:\n\n"
|
|
134
|
+
f" git-ssh-sync checkout {project} {branch}"
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
102
138
|
def _create_origin_branch(local_path: Path, branch: str, base_branch: str) -> None:
|
|
103
139
|
git.push(
|
|
104
140
|
"origin",
|
|
@@ -369,6 +405,47 @@ def _ensure_pushable(
|
|
|
369
405
|
)
|
|
370
406
|
|
|
371
407
|
|
|
408
|
+
def _ensure_pushable_from_development(
|
|
409
|
+
project: str, project_config: ProjectConfig, local_path: Path, branch: str
|
|
410
|
+
) -> None:
|
|
411
|
+
origin_head = git.rev_parse([f"refs/remotes/origin/{branch}"], cwd=local_path)
|
|
412
|
+
origin_commit = origin_head.stdout.strip()
|
|
413
|
+
result = ssh.run_remote_git(
|
|
414
|
+
project_config.dev.host,
|
|
415
|
+
project_config.dev.work_path,
|
|
416
|
+
["merge-base", "--is-ancestor", origin_commit, f"refs/heads/{branch}"],
|
|
417
|
+
user=project_config.dev.user,
|
|
418
|
+
check=False,
|
|
419
|
+
remote_os=project_config.dev.os,
|
|
420
|
+
)
|
|
421
|
+
if result.returncode == 0:
|
|
422
|
+
return
|
|
423
|
+
if result.returncode == 1:
|
|
424
|
+
current_branch = _remote_current_branch(project_config)
|
|
425
|
+
current_commit = _remote_short_head(project_config)
|
|
426
|
+
raise SyncError(
|
|
427
|
+
f"Cannot push {branch}.\n\n"
|
|
428
|
+
f"origin/{branch} has commits that are not included in dev/{branch}.\n\n"
|
|
429
|
+
f"Project:\n {project}\n\n"
|
|
430
|
+
"Development:\n"
|
|
431
|
+
f" host: {project_config.dev.host}\n"
|
|
432
|
+
f" path: {project_config.dev.work_path}\n"
|
|
433
|
+
f" branch: {current_branch}\n"
|
|
434
|
+
f" commit: {current_commit}\n\n"
|
|
435
|
+
"Run:\n\n"
|
|
436
|
+
f" git-ssh-sync pull {project}\n\n"
|
|
437
|
+
"Then resolve the branch on the development environment before pushing again."
|
|
438
|
+
)
|
|
439
|
+
raise CommandExecutionError(
|
|
440
|
+
environment=result.environment,
|
|
441
|
+
command=result.command,
|
|
442
|
+
returncode=result.returncode,
|
|
443
|
+
cwd=result.cwd,
|
|
444
|
+
stdout=result.stdout,
|
|
445
|
+
stderr=result.stderr,
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
|
|
372
449
|
def _load_project(project: str) -> ProjectConfig:
|
|
373
450
|
return get_project(load_config(), project)
|
|
374
451
|
|
|
@@ -456,12 +533,12 @@ def checkout_project(
|
|
|
456
533
|
operations = ["fetch origin in the gateway repository"]
|
|
457
534
|
if create:
|
|
458
535
|
base = base_branch or _require_remote_current_branch(project_config)
|
|
459
|
-
|
|
460
|
-
|
|
536
|
+
_ensure_origin_branch_on_remote(local_path, base)
|
|
537
|
+
_ensure_origin_branch_missing_on_remote(project, local_path, branch)
|
|
461
538
|
preflight.extend(
|
|
462
539
|
[
|
|
463
|
-
f"origin/{base} exists
|
|
464
|
-
f"origin/{branch} does not exist
|
|
540
|
+
f"origin/{base} exists on origin",
|
|
541
|
+
f"origin/{branch} does not exist on origin",
|
|
465
542
|
]
|
|
466
543
|
)
|
|
467
544
|
operations.extend(
|
|
@@ -470,12 +547,13 @@ def checkout_project(
|
|
|
470
547
|
f"fetch origin/{branch} into the gateway repository",
|
|
471
548
|
]
|
|
472
549
|
)
|
|
473
|
-
|
|
550
|
+
else:
|
|
551
|
+
_ensure_origin_branch_on_remote(local_path, branch)
|
|
474
552
|
_ensure_dev_clean(project, project_config)
|
|
475
553
|
branch_exists = _remote_branch_exists(project_config, branch)
|
|
476
554
|
preflight.extend(
|
|
477
555
|
[
|
|
478
|
-
f"origin/{branch} exists
|
|
556
|
+
f"origin/{branch} exists on origin",
|
|
479
557
|
"development work tree is clean",
|
|
480
558
|
]
|
|
481
559
|
)
|
|
@@ -527,7 +605,9 @@ def push_project(project: str, *, dry_run: bool = False) -> None:
|
|
|
527
605
|
if dry_run:
|
|
528
606
|
git.run_git(["fetch", "--dry-run", "origin"], cwd=local_path)
|
|
529
607
|
_ensure_origin_branch(local_path, selected_branch)
|
|
530
|
-
|
|
608
|
+
_ensure_pushable_from_development(
|
|
609
|
+
project, project_config, local_path, selected_branch
|
|
610
|
+
)
|
|
531
611
|
_print_dry_run_plan(
|
|
532
612
|
project=project,
|
|
533
613
|
branch=selected_branch,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|