FossilRepo
Fix sync: auto-create default 'fossilrepo' user in repo before pull
Commit
8879acdc92c9647a19e485a2f1ddb80d6887b7e547f0ef5a48dbf6a53b3e5775
Parent
d14eafa37f15972…
2 files changed
+29
+2
+29
| --- fossil/cli.py | ||
| +++ fossil/cli.py | ||
| @@ -21,10 +21,39 @@ | ||
| 21 | 21 | return {**os.environ, "USER": "fossilrepo"} |
| 22 | 22 | |
| 23 | 23 | def _run(self, *args: str, timeout: int = 30) -> subprocess.CompletedProcess: |
| 24 | 24 | cmd = [self.binary, *args] |
| 25 | 25 | return subprocess.run(cmd, capture_output=True, text=True, timeout=timeout, check=True, env=self._env) |
| 26 | + | |
| 27 | + def ensure_default_user(self, repo_path: Path, username: str = "fossilrepo") -> None: | |
| 28 | + """Ensure a default user exists in the repo. Creates if needed.""" | |
| 29 | + try: | |
| 30 | + # Check if user exists | |
| 31 | + result = subprocess.run( | |
| 32 | + [self.binary, "user", "list", "-R", str(repo_path)], | |
| 33 | + capture_output=True, | |
| 34 | + text=True, | |
| 35 | + timeout=10, | |
| 36 | + env=self._env, | |
| 37 | + ) | |
| 38 | + if username not in result.stdout: | |
| 39 | + subprocess.run( | |
| 40 | + [self.binary, "user", "new", username, "", username, "-R", str(repo_path)], | |
| 41 | + capture_output=True, | |
| 42 | + text=True, | |
| 43 | + timeout=10, | |
| 44 | + env=self._env, | |
| 45 | + ) | |
| 46 | + subprocess.run( | |
| 47 | + [self.binary, "user", "default", username, "-R", str(repo_path)], | |
| 48 | + capture_output=True, | |
| 49 | + text=True, | |
| 50 | + timeout=10, | |
| 51 | + env=self._env, | |
| 52 | + ) | |
| 53 | + except Exception: | |
| 54 | + pass | |
| 26 | 55 | |
| 27 | 56 | def init(self, path: Path) -> Path: |
| 28 | 57 | """Create a new .fossil repository.""" |
| 29 | 58 | path.parent.mkdir(parents=True, exist_ok=True) |
| 30 | 59 | self._run("init", str(path)) |
| 31 | 60 |
| --- fossil/cli.py | |
| +++ fossil/cli.py | |
| @@ -21,10 +21,39 @@ | |
| 21 | return {**os.environ, "USER": "fossilrepo"} |
| 22 | |
| 23 | def _run(self, *args: str, timeout: int = 30) -> subprocess.CompletedProcess: |
| 24 | cmd = [self.binary, *args] |
| 25 | return subprocess.run(cmd, capture_output=True, text=True, timeout=timeout, check=True, env=self._env) |
| 26 | |
| 27 | def init(self, path: Path) -> Path: |
| 28 | """Create a new .fossil repository.""" |
| 29 | path.parent.mkdir(parents=True, exist_ok=True) |
| 30 | self._run("init", str(path)) |
| 31 |
| --- fossil/cli.py | |
| +++ fossil/cli.py | |
| @@ -21,10 +21,39 @@ | |
| 21 | return {**os.environ, "USER": "fossilrepo"} |
| 22 | |
| 23 | def _run(self, *args: str, timeout: int = 30) -> subprocess.CompletedProcess: |
| 24 | cmd = [self.binary, *args] |
| 25 | return subprocess.run(cmd, capture_output=True, text=True, timeout=timeout, check=True, env=self._env) |
| 26 | |
| 27 | def ensure_default_user(self, repo_path: Path, username: str = "fossilrepo") -> None: |
| 28 | """Ensure a default user exists in the repo. Creates if needed.""" |
| 29 | try: |
| 30 | # Check if user exists |
| 31 | result = subprocess.run( |
| 32 | [self.binary, "user", "list", "-R", str(repo_path)], |
| 33 | capture_output=True, |
| 34 | text=True, |
| 35 | timeout=10, |
| 36 | env=self._env, |
| 37 | ) |
| 38 | if username not in result.stdout: |
| 39 | subprocess.run( |
| 40 | [self.binary, "user", "new", username, "", username, "-R", str(repo_path)], |
| 41 | capture_output=True, |
| 42 | text=True, |
| 43 | timeout=10, |
| 44 | env=self._env, |
| 45 | ) |
| 46 | subprocess.run( |
| 47 | [self.binary, "user", "default", username, "-R", str(repo_path)], |
| 48 | capture_output=True, |
| 49 | text=True, |
| 50 | timeout=10, |
| 51 | env=self._env, |
| 52 | ) |
| 53 | except Exception: |
| 54 | pass |
| 55 | |
| 56 | def init(self, path: Path) -> Path: |
| 57 | """Create a new .fossil repository.""" |
| 58 | path.parent.mkdir(parents=True, exist_ok=True) |
| 59 | self._run("init", str(path)) |
| 60 |
+2
| --- fossil/views.py | ||
| +++ fossil/views.py | ||
| @@ -967,10 +967,11 @@ | ||
| 967 | 967 | # Save remote URL configuration |
| 968 | 968 | url = request.POST.get("remote_url", "").strip() |
| 969 | 969 | if url: |
| 970 | 970 | fossil_repo.remote_url = url |
| 971 | 971 | fossil_repo.save(update_fields=["remote_url", "updated_at", "version"]) |
| 972 | + cli.ensure_default_user(fossil_repo.full_path) | |
| 972 | 973 | from django.contrib import messages |
| 973 | 974 | |
| 974 | 975 | messages.success(request, f"Sync configured: {url}") |
| 975 | 976 | from django.shortcuts import redirect |
| 976 | 977 | |
| @@ -988,10 +989,11 @@ | ||
| 988 | 989 | |
| 989 | 990 | return redirect("fossil:sync", slug=slug) |
| 990 | 991 | |
| 991 | 992 | elif action == "pull" and fossil_repo.remote_url: |
| 992 | 993 | if cli.is_available(): |
| 994 | + cli.ensure_default_user(fossil_repo.full_path) | |
| 993 | 995 | result = cli.pull(fossil_repo.full_path) |
| 994 | 996 | if result["success"]: |
| 995 | 997 | from django.utils import timezone |
| 996 | 998 | |
| 997 | 999 | fossil_repo.last_sync_at = timezone.now() |
| 998 | 1000 |
| --- fossil/views.py | |
| +++ fossil/views.py | |
| @@ -967,10 +967,11 @@ | |
| 967 | # Save remote URL configuration |
| 968 | url = request.POST.get("remote_url", "").strip() |
| 969 | if url: |
| 970 | fossil_repo.remote_url = url |
| 971 | fossil_repo.save(update_fields=["remote_url", "updated_at", "version"]) |
| 972 | from django.contrib import messages |
| 973 | |
| 974 | messages.success(request, f"Sync configured: {url}") |
| 975 | from django.shortcuts import redirect |
| 976 | |
| @@ -988,10 +989,11 @@ | |
| 988 | |
| 989 | return redirect("fossil:sync", slug=slug) |
| 990 | |
| 991 | elif action == "pull" and fossil_repo.remote_url: |
| 992 | if cli.is_available(): |
| 993 | result = cli.pull(fossil_repo.full_path) |
| 994 | if result["success"]: |
| 995 | from django.utils import timezone |
| 996 | |
| 997 | fossil_repo.last_sync_at = timezone.now() |
| 998 |
| --- fossil/views.py | |
| +++ fossil/views.py | |
| @@ -967,10 +967,11 @@ | |
| 967 | # Save remote URL configuration |
| 968 | url = request.POST.get("remote_url", "").strip() |
| 969 | if url: |
| 970 | fossil_repo.remote_url = url |
| 971 | fossil_repo.save(update_fields=["remote_url", "updated_at", "version"]) |
| 972 | cli.ensure_default_user(fossil_repo.full_path) |
| 973 | from django.contrib import messages |
| 974 | |
| 975 | messages.success(request, f"Sync configured: {url}") |
| 976 | from django.shortcuts import redirect |
| 977 | |
| @@ -988,10 +989,11 @@ | |
| 989 | |
| 990 | return redirect("fossil:sync", slug=slug) |
| 991 | |
| 992 | elif action == "pull" and fossil_repo.remote_url: |
| 993 | if cli.is_available(): |
| 994 | cli.ensure_default_user(fossil_repo.full_path) |
| 995 | result = cli.pull(fossil_repo.full_path) |
| 996 | if result["success"]: |
| 997 | from django.utils import timezone |
| 998 | |
| 999 | fossil_repo.last_sync_at = timezone.now() |
| 1000 |