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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9e3e6d8ef83b129d25ae1ebdabed11a54de9663ca621bd1d8d54ec2eb1a739df
4
- data.tar.gz: ce3534e62b84e8c356a5e16a5a0e28d4f44f2ac9071b30c066eb798a4898a3ec
3
+ metadata.gz: 19527d7bf5bd6af3f94eec7673a0b60ebedc3080adc1308ba23e477b874af8f1
4
+ data.tar.gz: 1a29bde8db351846148a7832d57f6cd2736e3d88941267f21a2699a05a982131
5
5
  SHA512:
6
- metadata.gz: 9d9689456562cef5bfccd4931405445732c7f183f2783a73a506d1d0c1321298d21b647f67bc551883b9e3c6ef1ce3cde41fc3c2292886fd98a60660f1723b2d
7
- data.tar.gz: 63973a9fe55d4899070067c585842f41aaf714252c4f745545226d1450fa12cf5931ce2f84cf0ab939ae695f28cec7b885a04bc729b807230487f9553ad17887
6
+ metadata.gz: cbf4077b51bd7a4dca8cb9ef8eafc53afe3ce0c2068d954f565e7b9d76cb524350b0c4254c417456e4dc0d8dcd0554ae895767cfcce46b9f4f4abe31a5d5222a
7
+ data.tar.gz: df450cc45d5d36007c9f629e1c6b296425c49510240e652e89593fb0c02181d4f0547b27d423bfec70a7c381b80ba4c56551fea8523eaa28447669e5d392026c
@@ -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
- def initialize(config:, api: Api.new(server: config.server), out: $stdout, name: Socket.gethostname,
13
- sleeper: ->(seconds) { sleep(seconds) }, opener: ->(url) { Login.open_browser(url) }, clock: -> { Time.now })
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 companion never
28
- # touches the clipboard.
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 " Your code: #{code}"
45
+ @out.puts @copier.call(code) ? "! One-time code (#{code}) copied to clipboard" : "! One-time code: #{code}"
32
46
  @out.puts
33
- @out.puts "Enter it at #{uri}, press Pair, then check the device details and press Approve."
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
- @opener.call(uri)
36
- poll(auth)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Diffbroker
4
- VERSION = "0.15.1"
4
+ VERSION = "0.16.0"
5
5
  end
@@ -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
- @runner.git(repo_path, "fetch", "--quiet", remote, "+refs/pull/#{number}/head:refs/diffbroker/pr-#{number}")
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/)
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "diffbroker",
3
- "version": "0.15.1",
3
+ "version": "0.16.0",
4
4
  "description": "Skills for working on Diff Broker agent tasks: the diffbroker MCP tools, write rules and report_task."
5
5
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: diffbroker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.1
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuri Sidorov (@newstler)