diffbroker 0.15.1 → 0.16.0
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/diffbroker/login.rb +32 -8
- data/lib/diffbroker/version.rb +1 -1
- data/lib/diffbroker/worktree.rb +12 -1
- 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: 19527d7bf5bd6af3f94eec7673a0b60ebedc3080adc1308ba23e477b874af8f1
|
|
4
|
+
data.tar.gz: 1a29bde8db351846148a7832d57f6cd2736e3d88941267f21a2699a05a982131
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cbf4077b51bd7a4dca8cb9ef8eafc53afe3ce0c2068d954f565e7b9d76cb524350b0c4254c417456e4dc0d8dcd0554ae895767cfcce46b9f4f4abe31a5d5222a
|
|
7
|
+
data.tar.gz: df450cc45d5d36007c9f629e1c6b296425c49510240e652e89593fb0c02181d4f0547b27d423bfec70a7c381b80ba4c56551fea8523eaa28447669e5d392026c
|
data/lib/diffbroker/login.rb
CHANGED
|
@@ -9,14 +9,28 @@ module Diffbroker
|
|
|
9
9
|
system(Diffbroker.platform == "macos" ? "open" : "xdg-open", url, out: File::NULL, err: File::NULL)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
# Best effort: true when a clipboard tool took the text.
|
|
13
|
+
def self.copy_to_clipboard(text)
|
|
14
|
+
tool = case Diffbroker.platform
|
|
15
|
+
when "macos" then %w[pbcopy]
|
|
16
|
+
else [ %w[wl-copy], %w[xclip -selection clipboard], %w[xsel --clipboard --input] ].find { system("which", _1.first, out: File::NULL, err: File::NULL) }
|
|
17
|
+
end
|
|
18
|
+
tool ? IO.popen(tool, "w") { _1.write(text) } && $?.success? : false
|
|
19
|
+
rescue SystemCallError
|
|
20
|
+
false
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def initialize(config:, api: Api.new(server: config.server), out: $stdout, name: Socket.gethostname, input: $stdin,
|
|
24
|
+
sleeper: ->(seconds) { sleep(seconds) }, opener: ->(url) { Login.open_browser(url) },
|
|
25
|
+
copier: ->(text) { Login.copy_to_clipboard(text) }, clock: -> { Time.now })
|
|
14
26
|
@config = config
|
|
15
27
|
@api = api
|
|
16
28
|
@out = out
|
|
29
|
+
@input = input
|
|
17
30
|
@name = name
|
|
18
31
|
@sleeper = sleeper
|
|
19
32
|
@opener = opener
|
|
33
|
+
@copier = copier
|
|
20
34
|
@clock = clock
|
|
21
35
|
end
|
|
22
36
|
|
|
@@ -24,20 +38,30 @@ module Diffbroker
|
|
|
24
38
|
auth = @api.post("/device_authorizations", { client_name: @name, platform: Diffbroker.platform })
|
|
25
39
|
code = auth.fetch("user_code")
|
|
26
40
|
uri = auth.fetch("verification_uri")
|
|
27
|
-
# No pre-filled link: nothing in a URL may select a code, the user types it on the plain page. The
|
|
28
|
-
#
|
|
41
|
+
# No pre-filled link: nothing in a URL may select a code, the user types (or pastes) it on the plain page. The browser
|
|
42
|
+
# opens only when the user presses Enter, never by itself; without a terminal it does not open at all.
|
|
29
43
|
@out.puts "Pairing #{@name} with Diff Broker."
|
|
30
44
|
@out.puts
|
|
31
|
-
@out.puts "
|
|
45
|
+
@out.puts @copier.call(code) ? "! One-time code (#{code}) copied to clipboard" : "! One-time code: #{code}"
|
|
32
46
|
@out.puts
|
|
33
|
-
|
|
47
|
+
if interactive?
|
|
48
|
+
@out.puts "Press Enter to open #{uri} in your browser, press Pair, then check the device details and press Approve."
|
|
49
|
+
enter = Thread.new { @opener.call(uri) if @input.gets }
|
|
50
|
+
else
|
|
51
|
+
@out.puts "Open #{uri}, enter the code, press Pair, then check the device details and press Approve."
|
|
52
|
+
end
|
|
34
53
|
@out.puts "Only enter a code you see here, in your own terminal."
|
|
35
|
-
|
|
36
|
-
|
|
54
|
+
begin
|
|
55
|
+
poll(auth)
|
|
56
|
+
ensure
|
|
57
|
+
enter&.kill
|
|
58
|
+
end
|
|
37
59
|
end
|
|
38
60
|
|
|
39
61
|
private
|
|
40
62
|
|
|
63
|
+
def interactive? = @input.respond_to?(:tty?) && @input.tty?
|
|
64
|
+
|
|
41
65
|
def poll(auth)
|
|
42
66
|
interval = auth.fetch("interval", 5).to_i
|
|
43
67
|
deadline = @clock.call + auth.fetch("expires_in", 600).to_i
|
data/lib/diffbroker/version.rb
CHANGED
data/lib/diffbroker/worktree.rb
CHANGED
|
@@ -25,7 +25,7 @@ module Diffbroker
|
|
|
25
25
|
dir = File.join(@root, full_name.downcase.tr("/", "-"), "pr-#{number}-#{kind}")
|
|
26
26
|
|
|
27
27
|
remote = GitContext.remote_for(repo_path, full_name)
|
|
28
|
-
|
|
28
|
+
fetch_pull!(repo_path, remote, full_name, number)
|
|
29
29
|
unless @runner.git_success?(repo_path, "cat-file", "-e", "#{head_sha}^{commit}")
|
|
30
30
|
raise Error, "Head #{head_sha[0, 7]} is not in the fetched PR; the PR may have moved. Start the task again from the card."
|
|
31
31
|
end
|
|
@@ -105,6 +105,17 @@ module Diffbroker
|
|
|
105
105
|
@runner.git_success?(repo_path, "branch", "--quiet", "--unset-upstream", local)
|
|
106
106
|
end
|
|
107
107
|
|
|
108
|
+
# git's refusal is several lines and the server keeps only the last, so it becomes one line: what was fetched, git's own
|
|
109
|
+
# words and the command that shows the same failure in a terminal. The usual cause is the background service lacking the
|
|
110
|
+
# credentials (SSH key, credential helper) this machine's terminal has.
|
|
111
|
+
def fetch_pull!(repo_path, remote, full_name, number)
|
|
112
|
+
@runner.git(repo_path, "fetch", "--quiet", remote, "+refs/pull/#{number}/head:refs/diffbroker/pr-#{number}")
|
|
113
|
+
rescue Error => e
|
|
114
|
+
reason = e.message.sub(/\A.*? failed: /m, "").split.join(" ")
|
|
115
|
+
raise Error, "Could not fetch #{full_name}##{number} from #{remote} (#{reason}). " \
|
|
116
|
+
"Check that `git -C #{repo_path} fetch #{remote}` works on this computer, then `diffbroker restart`."
|
|
117
|
+
end
|
|
118
|
+
|
|
108
119
|
def validate!(full_name:, number:, head_sha:, kind:)
|
|
109
120
|
raise Error, "Invalid head SHA #{head_sha.inspect}" unless head_sha.to_s.match?(SHA)
|
|
110
121
|
raise Error, "Invalid PR number #{number.inspect}" unless number.to_s.match?(/\A[1-9]\d{0,9}\z/)
|