gitbroker 0.6.2 → 0.6.4
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.
- checksums.yaml +4 -4
- data/lib/gitbroker/cli.rb +22 -2
- data/lib/gitbroker/daemon.rb +1 -1
- data/lib/gitbroker/lifecycle.rb +16 -5
- data/lib/gitbroker/version.rb +1 -1
- data/lib/gitbroker/worktree.rb +21 -0
- data/plugin/.claude-plugin/plugin.json +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b6c41dc04d47bc8bfbad2ccb322b3a952b58e4957c2e282c25cb9075e58e83b2
|
|
4
|
+
data.tar.gz: 6d2f1b148005c310ed3538fe6fc4349cbaa38821bd1aa0f2ef25117477f146fa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 271fb887ec812d171902d32a53ed027bd3107194c19e0d67f14a1e5d22352f143add06b8090f2ba9ddd57e5853e35c773541234ad50d4666a064d49a9683513f
|
|
7
|
+
data.tar.gz: 9a259bd5c66d1836d85b23f7e017a4011ff28722cd068f5eaeaf746eb7be8e0d2d6dbf578067cd529ed9a8858e9970fd1712d6feabc39a505afca5d9f3bd69bc
|
data/lib/gitbroker/cli.rb
CHANGED
|
@@ -103,13 +103,33 @@ module Gitbroker
|
|
|
103
103
|
parser.on("--name NAME") { options[:name] = _1 }
|
|
104
104
|
parser.on("--foreground") { options[:foreground] = true }
|
|
105
105
|
end.parse!(@argv)
|
|
106
|
-
|
|
106
|
+
foreground = options[:foreground] || !@input.tty?
|
|
107
|
+
if options[:server]
|
|
108
|
+
# Setting a machine up remembers its server (the background service must use it too). A daemon run by hand only
|
|
109
|
+
# uses it for this run: it must not rewrite the settings the service reads.
|
|
110
|
+
@config = foreground ? Config.load(dir: Config.default_dir(@env), env: @env.merge("GITBROKER_SERVER" => options[:server])) : config.save!("server" => options[:server])
|
|
111
|
+
end
|
|
107
112
|
|
|
108
|
-
return run_daemon if
|
|
113
|
+
return run_daemon if foreground
|
|
114
|
+
return set_up_separate_instance(options[:name] || Socket.gethostname) if separate_instance?
|
|
109
115
|
|
|
110
116
|
set_up(options[:name] || Socket.gethostname)
|
|
111
117
|
end
|
|
112
118
|
|
|
119
|
+
# A GITBROKER_CONFIG_DIR that is not the default is another companion (say, one for a local dev server). The background
|
|
120
|
+
# service belongs to the default one, so this one is paired and then kept in this window; it never touches the service.
|
|
121
|
+
def separate_instance?
|
|
122
|
+
custom = @env["GITBROKER_CONFIG_DIR"]
|
|
123
|
+
custom && File.expand_path(custom) != File.expand_path(Config.default_dir(@env.reject { |key, _| key == "GITBROKER_CONFIG_DIR" }))
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def set_up_separate_instance(name)
|
|
127
|
+
Login.new(config:, out: @out, name:).run unless config.paired?
|
|
128
|
+
@out.puts "This companion uses its own settings (#{config.dir}), so the background service is left alone. Keeping it in this " \
|
|
129
|
+
"window, connected to #{config.server}; press Ctrl-C to stop it."
|
|
130
|
+
run_daemon
|
|
131
|
+
end
|
|
132
|
+
|
|
113
133
|
def run_daemon
|
|
114
134
|
raise Error, "This machine is not paired. Run `gitbroker start` in a terminal to pair it." unless config.paired?
|
|
115
135
|
|
data/lib/gitbroker/daemon.rb
CHANGED
|
@@ -26,7 +26,7 @@ module Gitbroker
|
|
|
26
26
|
new(scanner: RepoScanner.new(roots: config.roots, depth: config.scan_depth, exclude: [ config.worktree_root ]),
|
|
27
27
|
client_factory: -> { CableClient.new(url: config.cable_url, token: config.device_token, origin: config.server) },
|
|
28
28
|
task_runner_factory: ->(report) { TaskRunner.new(config:, report:, out:) }, out:, relay:, process_scanner:,
|
|
29
|
-
lifecycle: Lifecycle.new(dir: config.dir))
|
|
29
|
+
lifecycle: Lifecycle.new(dir: config.dir, server: config.server))
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
# Claude sessions with hooks installed report real working/waiting status, so the scanner only looks for `claude`
|
data/lib/gitbroker/lifecycle.rb
CHANGED
|
@@ -12,7 +12,7 @@ module Gitbroker
|
|
|
12
12
|
WAIT = 10
|
|
13
13
|
|
|
14
14
|
def initialize(dir:, home: Dir.home, service: ServiceInstaller.new(home:), runner: Runner.new, exe: ServiceInstaller.launcher,
|
|
15
|
-
ruby: RbConfig.ruby, spawner: nil, sleeper: ->(seconds) { sleep(seconds) }, pid: Process.pid)
|
|
15
|
+
ruby: RbConfig.ruby, spawner: nil, sleeper: ->(seconds) { sleep(seconds) }, pid: Process.pid, env: ENV, server: nil)
|
|
16
16
|
@dir = dir
|
|
17
17
|
@home = home
|
|
18
18
|
@service = service
|
|
@@ -22,6 +22,8 @@ module Gitbroker
|
|
|
22
22
|
@spawner = spawner || method(:spawn_process)
|
|
23
23
|
@sleeper = sleeper
|
|
24
24
|
@pid = pid
|
|
25
|
+
@env = env
|
|
26
|
+
@server = server
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
attr_reader :service
|
|
@@ -41,9 +43,15 @@ module Gitbroker
|
|
|
41
43
|
nil
|
|
42
44
|
end
|
|
43
45
|
|
|
44
|
-
#
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
# True only for the daemon the service manager started (launchd sets XPC_SERVICE_NAME to the job's label, systemd sets
|
|
47
|
+
# INVOCATION_ID). A daemon started by hand (`gitbroker start --server http://localhost:3000`) is not the service's:
|
|
48
|
+
# asking the manager to restart or stop "the service" would act on a different process (the one pointed at the
|
|
49
|
+
# default server) and leave this one running its old code for ever.
|
|
50
|
+
def service_process? = @env["XPC_SERVICE_NAME"] == ServiceInstaller::LABEL || @env.key?("INVOCATION_ID")
|
|
51
|
+
|
|
52
|
+
# Used by the daemon itself: false when this is not the service's daemon, no service is installed or the manager refused.
|
|
53
|
+
def stop_service = service_process? && @service.installed? && @service.stop!
|
|
54
|
+
def restart_service = service_process? && @service.installed? && @service.restart!
|
|
47
55
|
|
|
48
56
|
# Starts the background service, or the daemon itself when none is installed. False when a service was refused.
|
|
49
57
|
def launch
|
|
@@ -109,8 +117,11 @@ module Gitbroker
|
|
|
109
117
|
false
|
|
110
118
|
end
|
|
111
119
|
|
|
120
|
+
# The respawned daemon talks to the server this one did (a daemon started by hand against a local server must not come
|
|
121
|
+
# back pointed at the default one).
|
|
112
122
|
def spawn_process(argv, log)
|
|
113
|
-
|
|
123
|
+
env = @server ? { "GITBROKER_SERVER" => @server } : {}
|
|
124
|
+
Process.detach(Process.spawn(env, *argv, in: File::NULL, out: [ log, "a" ], err: [ log, "a" ], pgroup: true))
|
|
114
125
|
end
|
|
115
126
|
end
|
|
116
127
|
end
|
data/lib/gitbroker/version.rb
CHANGED
data/lib/gitbroker/worktree.rb
CHANGED
|
@@ -30,6 +30,7 @@ module Gitbroker
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
local = "gitbroker/pr-#{number}-#{kind}"
|
|
33
|
+
retire_leftovers!(repo_path, dir, local, head_sha) if branch && kind == "update_branch"
|
|
33
34
|
keep_local_commits!(repo_path, local, head_sha) if branch
|
|
34
35
|
if File.exist?(File.join(dir, ".git"))
|
|
35
36
|
reuse(dir, local, head_sha, branch:)
|
|
@@ -64,6 +65,26 @@ module Gitbroker
|
|
|
64
65
|
branch ? @runner.git(dir, "checkout", "--quiet", "-B", local, head_sha) : @runner.git(dir, "checkout", "--quiet", "--detach", head_sha)
|
|
65
66
|
end
|
|
66
67
|
|
|
68
|
+
# An update_branch task rewrites its branch, so what an earlier attempt left behind (an unpushed rebase, a half-finished
|
|
69
|
+
# one, a dirty worktree) is not work to protect but a result to redo: it is set aside, never deleted (the worktree is
|
|
70
|
+
# moved and the branch renamed, both with a `-leftover-<time>` suffix that `gitbroker clean` can remove), and the task
|
|
71
|
+
# starts from the PR head.
|
|
72
|
+
def retire_leftovers!(repo_path, dir, local, head_sha)
|
|
73
|
+
stamp = Time.now.strftime("%Y%m%d%H%M%S")
|
|
74
|
+
if File.exist?(File.join(dir, ".git"))
|
|
75
|
+
pristine = @runner.git(dir, "status", "--porcelain").strip.empty? && @runner.git(dir, "rev-parse", "HEAD").strip.start_with?(head_sha)
|
|
76
|
+
unless pristine
|
|
77
|
+
moved = "#{dir}-leftover-#{stamp}"
|
|
78
|
+
@runner.git(repo_path, "worktree", "move", dir, moved)
|
|
79
|
+
@runner.git(moved, "checkout", "--quiet", "--detach") # frees the task branch; the files stay as they were
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
return unless @runner.git_success?(repo_path, "rev-parse", "--verify", "--quiet", "refs/heads/#{local}")
|
|
83
|
+
return if @runner.git_success?(repo_path, "merge-base", "--is-ancestor", "refs/heads/#{local}", head_sha)
|
|
84
|
+
|
|
85
|
+
@runner.git(repo_path, "branch", "--quiet", "-m", local, "#{local}-leftover-#{stamp}")
|
|
86
|
+
end
|
|
87
|
+
|
|
67
88
|
# `-B` resets the task branch to the head; refuse when that would drop commits made there that the head lacks.
|
|
68
89
|
def keep_local_commits!(repo_path, local, head_sha)
|
|
69
90
|
return unless @runner.git_success?(repo_path, "rev-parse", "--verify", "--quiet", "refs/heads/#{local}")
|