gitbroker 0.7.0 → 0.7.1

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: cdb076d007739b3e1eb411ac473ffe84dc28423a2ad78065a4aa33d14f11bbd9
4
- data.tar.gz: 93e99568aba514f872f45e8f445ca9f1c40fdc8d0ffccfdbd1b454feb3008a54
3
+ metadata.gz: d89c372f196a3cd8b81d057f63c8abcdafa765585fcde6abaa15dd8ec81c48bf
4
+ data.tar.gz: 473d304e0ed3fe9bafc232490e4be505b17b12b09c2cebf6b194d2547b108203
5
5
  SHA512:
6
- metadata.gz: b87041c66a6a11b01ab1003ee3912e7bddc8cb2ccdd7d8b6c6162bc4da04320530c621d941024b059dbe13080088b8d21112b7f47a24481d76369930093eea9a
7
- data.tar.gz: 57b801d31d18aae68cb9bf52e9e58a890a9fa9b41cddbc7c43eb3cc9aed227fca3064bdca72b58b9523630855aa3c657c899915da79d45d8f3ecb55199e37a81
6
+ metadata.gz: c0d446a0a798acb225933b1cd4c1f31c3425112ac025a2bc684b468e47bc57869b56f892683a4c278cbbb788ac5cd7f5f56fa8286671c98d160d115d72313c4c
7
+ data.tar.gz: 3914718aa114dfe375b4783dfe9c6d5e0408d43d319c013e400f4628912e15984f937417043409b6dfd9b3766cb2e6c3ed7f2a74ae678cc52813a35f57560f81
@@ -63,8 +63,13 @@ module Gitbroker
63
63
  def cable_url = "#{server.sub(/\Ahttp/, "ws")}/cable"
64
64
  # `roots` in config.yml and the folders added in Git Broker (`device_roots`) add to the usual folders; the checkouts Claude Code and Codex know come in through `repo_scanner`.
65
65
  def device_roots = self.class.clean_device_roots(data["device_roots"], home:)
66
+ def ignored_roots = self.class.clean_device_roots(data["ignored_roots"], home:)
66
67
  def roots = (self.class.common_roots(home) + Array(data["roots"]).map { File.expand_path(_1.to_s.sub(/\A~/, home)) } + device_roots).uniq
67
- def repo_scanner = RepoScanner.new(roots:, depth: scan_depth, exclude: [ worktree_root ], hints: AgentProjects.paths(home:), home:)
68
+ # Folders the user removed in Git Broker (`ignored_roots`) are skipped everywhere except inside a folder they added.
69
+ def repo_scanner
70
+ RepoScanner.new(roots: roots - device_roots, explicit_roots: device_roots, depth: scan_depth, exclude: [ worktree_root ],
71
+ ignored: ignored_roots, hints: AgentProjects.paths(home:), home:)
72
+ end
68
73
  def scan_depth = Integer(data["scan_depth"] || 3)
69
74
  def terminal = (data["terminal"] || (@platform == "macos" ? "terminal" : "tmux")).to_s
70
75
  def worktree_root = File.expand_path(data["worktree_root"] || File.join(home, ".local/share/gitbroker/worktrees"))
@@ -23,7 +23,7 @@ module Gitbroker
23
23
  process_scanner: build_process_scanner(config))
24
24
  raise Error, "This machine is not paired. Run `gitbroker start` in a terminal to pair it." unless config.paired?
25
25
 
26
- new(scanner: config.repo_scanner, roots_changed: roots_changed(config), device_roots: config.device_roots,
26
+ new(scanner: config.repo_scanner, roots_changed: roots_changed(config), device_roots: config.device_roots, ignored_roots: config.ignored_roots,
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
29
  lifecycle: Lifecycle.new(dir: config.dir, server: config.server))
@@ -33,8 +33,8 @@ module Gitbroker
33
33
  # scan with them from now on. Returns the new scanner.
34
34
  def self.roots_changed(config)
35
35
  current = config
36
- lambda do |roots|
37
- current = current.save!("device_roots" => roots.empty? ? nil : roots)
36
+ lambda do |roots, ignored|
37
+ current = current.save!("device_roots" => roots.empty? ? nil : roots, "ignored_roots" => ignored.empty? ? nil : ignored)
38
38
  current.repo_scanner
39
39
  end
40
40
  end
@@ -54,9 +54,10 @@ module Gitbroker
54
54
 
55
55
  def initialize(scanner:, client_factory:, task_runner_factory:, out: $stdout, sleeper: ->(seconds) { sleep(seconds) },
56
56
  clock: -> { Time.now }, spawner: ->(&block) { Thread.new(&block) }, relay: nil, process_scanner: nil, lifecycle: nil,
57
- maintenance: Maintenance.new, roots_changed: nil, device_roots: [])
57
+ maintenance: Maintenance.new, roots_changed: nil, device_roots: [], ignored_roots: [])
58
58
  @scanner = scanner
59
59
  @device_roots = device_roots
60
+ @ignored_roots = ignored_roots
60
61
  @roots_changed = roots_changed
61
62
  @client_factory = client_factory
62
63
  @task_runner = task_runner_factory.call(method(:report))
@@ -221,7 +222,7 @@ module Gitbroker
221
222
 
222
223
  def handle(client, message)
223
224
  return control(message["action"]) if message["type"] == "control"
224
- return apply_roots(client, message["roots"]) if message["type"] == "roots"
225
+ return apply_roots(client, message["roots"], message["ignored"]) if message["type"] == "roots"
225
226
 
226
227
  id = message["task_id"]
227
228
  return unless id.is_a?(String)
@@ -234,14 +235,16 @@ module Gitbroker
234
235
  end
235
236
 
236
237
  # Sent on every connection and whenever the user changes the list. Nothing happens when it is what we already scan.
237
- def apply_roots(client, roots)
238
+ def apply_roots(client, roots, ignored)
238
239
  return unless @roots_changed
239
240
 
240
241
  clean = Config.clean_device_roots(roots, home: Dir.home)
241
- return if clean == @device_roots
242
+ clean_ignored = Config.clean_device_roots(ignored, home: Dir.home)
243
+ return if clean == @device_roots && clean_ignored == @ignored_roots
242
244
 
243
245
  @device_roots = clean
244
- @scanner = @roots_changed.call(clean)
246
+ @ignored_roots = clean_ignored
247
+ @scanner = @roots_changed.call(clean, clean_ignored)
245
248
  rescan(client)
246
249
  end
247
250
 
@@ -19,19 +19,25 @@ module Gitbroker
19
19
  HINT_LEVELS = 4
20
20
  HINT_PARENT_DEPTH = 2
21
21
 
22
- def initialize(roots:, depth: 3, exclude: [], hints: [], home: Dir.home)
22
+ # `exclude` (the task worktrees) is skipped everywhere. `ignored` (folders the user removed) is skipped by everything
23
+ # found by itself; `explicit_roots` (folders the user added) are scanned even inside an ignored folder.
24
+ def initialize(roots:, depth: 3, exclude: [], hints: [], home: Dir.home, explicit_roots: [], ignored: [])
23
25
  @roots = roots
26
+ @explicit_roots = explicit_roots
27
+ @ignored = ignored.map { File.expand_path(_1) }
24
28
  @hints = hints
25
29
  @home = File.expand_path(home)
26
30
  @depth = depth
27
31
  @exclude = exclude.map { File.expand_path(_1) }
32
+ @skip = @exclude + @ignored
28
33
  end
29
34
 
30
35
  def scan
31
36
  found = {}
32
- @roots.each { |root| walk(File.expand_path(root), 0, found) if File.directory?(root) }
37
+ @roots.each { |root| walk(File.expand_path(root), 0, found, @depth, @skip) if File.directory?(root) }
38
+ @explicit_roots.each { |root| walk(File.expand_path(root), 0, found, @depth, @exclude) if File.directory?(root) }
33
39
  parents = @hints.filter_map { |hint| add_hint(File.expand_path(hint), found) }.map { File.dirname(_1) }.uniq
34
- parents.each { |parent| walk(parent, 0, found, HINT_PARENT_DEPTH) if scannable_parent?(parent) }
40
+ parents.each { |parent| walk(parent, 0, found, HINT_PARENT_DEPTH, @skip) if scannable_parent?(parent) }
35
41
  found.sort.map { |full_name, path| { "full_name" => full_name, "path" => path } }
36
42
  end
37
43
 
@@ -40,7 +46,7 @@ module Gitbroker
40
46
  # Records the checkout a hint is in and returns its directory (nil when it is not in one).
41
47
  def add_hint(dir, found)
42
48
  HINT_LEVELS.times do
43
- return nil if @exclude.any? { |excluded| dir == excluded || dir.start_with?("#{excluded}/") }
49
+ return nil if @skip.any? { |skipped| dir == skipped || dir.start_with?("#{skipped}/") }
44
50
  return nil unless File.directory?(dir)
45
51
 
46
52
  if File.exist?(File.join(dir, ".git"))
@@ -58,8 +64,8 @@ module Gitbroker
58
64
  !(dir == @home || dir == "/" || @home.start_with?("#{dir}/"))
59
65
  end
60
66
 
61
- def walk(dir, level, found, limit = @depth)
62
- return if @exclude.any? { |excluded| dir == excluded || dir.start_with?("#{excluded}/") }
67
+ def walk(dir, level, found, limit, skip)
68
+ return if skip.any? { |skipped| dir == skipped || dir.start_with?("#{skipped}/") }
63
69
 
64
70
  if File.exist?(File.join(dir, ".git"))
65
71
  remote_names(dir).each { |name| found[name] = dir if found[name].nil? || dir.length < found[name].length }
@@ -71,7 +77,7 @@ module Gitbroker
71
77
  next if child.start_with?(".") || SKIP.include?(child)
72
78
 
73
79
  path = File.join(dir, child)
74
- walk(path, level + 1, found, limit) if File.directory?(path) && !File.symlink?(path)
80
+ walk(path, level + 1, found, limit, skip) if File.directory?(path) && !File.symlink?(path)
75
81
  end
76
82
  rescue Errno::EACCES, Errno::ENOENT, Errno::ENOTDIR
77
83
  nil
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Gitbroker
4
- VERSION = "0.7.0"
4
+ VERSION = "0.7.1"
5
5
  end
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "gitbroker",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "Skills for working on Git Broker agent tasks: the gitbroker MCP tools, write rules and report_task."
5
5
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitbroker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuri Sidorov (@newstler)