aidp 0.49.8 → 0.49.10
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/aidp/pr_worktree_manager.rb +23 -13
- data/lib/aidp/shell_executor.rb +38 -4
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp/watch/rebase_processor.rb +19 -12
- 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: 2edfd145fd098c930d76688336659919ad8fa5a4df4cb9f5c3aa5434a60d425f
|
|
4
|
+
data.tar.gz: c5a1a71bd5adb17cd850484964f11750e7d10e7d5c05e9aa366c89f700794d31
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 21667ac8aae592117e34e738b74eb3b01c2f941a9a5672f54ae6e1549bff56289e5bf62e568caf6a08b3a492d17db22e01ba4d28e1a2944e2259d6214a83a2b4
|
|
7
|
+
data.tar.gz: d4f213b4e236003cccbdb5dbbb5dd41be6e9ce4448cdbda52900a0f651a6939d1801cfe201d3ef35b9ed2218caa04f8aa130e8d5479e3eeccf4cefdda2be615b
|
|
@@ -434,19 +434,16 @@ module Aidp
|
|
|
434
434
|
push_result[:git_actions][:staged_changes] = true
|
|
435
435
|
push_result[:changed_files] = staged_changes_output.split("\n")
|
|
436
436
|
|
|
437
|
-
#
|
|
438
|
-
|
|
439
|
-
commit_command = "git commit -m '#{commit_message}' 2>&1"
|
|
440
|
-
commit_output = @shell_executor.run(commit_command).strip
|
|
437
|
+
# Commit staged changes without shell interpretation of library input
|
|
438
|
+
commit_output = commit_staged_changes(pr_number)
|
|
441
439
|
|
|
442
|
-
if
|
|
440
|
+
if commit_output.success?
|
|
443
441
|
push_result[:git_actions][:committed] = true
|
|
444
442
|
|
|
445
|
-
#
|
|
446
|
-
|
|
447
|
-
push_output = @shell_executor.run(push_command).strip
|
|
443
|
+
# Push the registry-sourced head branch without shell interpretation
|
|
444
|
+
push_output = push_head_branch(head_branch)
|
|
448
445
|
|
|
449
|
-
if
|
|
446
|
+
if push_output.success?
|
|
450
447
|
push_result[:git_actions][:pushed] = true
|
|
451
448
|
push_result[:success] = true
|
|
452
449
|
|
|
@@ -458,22 +455,22 @@ module Aidp
|
|
|
458
455
|
)
|
|
459
456
|
else
|
|
460
457
|
# Detailed push error logging
|
|
461
|
-
push_result[:errors] << "Push failed: #{push_output}"
|
|
458
|
+
push_result[:errors] << "Push failed: #{push_output.output.strip}"
|
|
462
459
|
Aidp.log_error(
|
|
463
460
|
"pr_worktree_manager", "push_changes_failed",
|
|
464
461
|
pr_number: pr_number,
|
|
465
462
|
branch: head_branch,
|
|
466
|
-
error_details: push_output
|
|
463
|
+
error_details: push_output.output.strip
|
|
467
464
|
)
|
|
468
465
|
end
|
|
469
466
|
else
|
|
470
467
|
# Detailed commit error logging
|
|
471
|
-
push_result[:errors] << "Commit failed: #{commit_output}"
|
|
468
|
+
push_result[:errors] << "Commit failed: #{commit_output.output.strip}"
|
|
472
469
|
Aidp.log_error(
|
|
473
470
|
"pr_worktree_manager", "commit_changes_failed",
|
|
474
471
|
pr_number: pr_number,
|
|
475
472
|
branch: head_branch,
|
|
476
|
-
error_details: commit_output
|
|
473
|
+
error_details: commit_output.output.strip
|
|
477
474
|
)
|
|
478
475
|
end
|
|
479
476
|
else
|
|
@@ -532,6 +529,19 @@ module Aidp
|
|
|
532
529
|
|
|
533
530
|
private
|
|
534
531
|
|
|
532
|
+
# Commit currently staged changes; argv execution keeps externally
|
|
533
|
+
# sourced values (pr_number) from being interpreted by a shell
|
|
534
|
+
def commit_staged_changes(pr_number)
|
|
535
|
+
commit_message = "Changes applied via AIDP request-changes workflow for PR ##{pr_number}"
|
|
536
|
+
@shell_executor.run_argv("git", "commit", "-m", commit_message)
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
# Push the head branch; argv execution keeps registry-sourced branch
|
|
540
|
+
# names from being interpreted by a shell
|
|
541
|
+
def push_head_branch(head_branch)
|
|
542
|
+
@shell_executor.run_argv("git", "push", "origin", "--", head_branch)
|
|
543
|
+
end
|
|
544
|
+
|
|
535
545
|
# Load the worktree registry from file
|
|
536
546
|
def load_registry
|
|
537
547
|
return {} unless File.exist?(worktree_registry_path)
|
data/lib/aidp/shell_executor.rb
CHANGED
|
@@ -25,6 +25,32 @@ module Aidp
|
|
|
25
25
|
end
|
|
26
26
|
self.suppress_output = false
|
|
27
27
|
|
|
28
|
+
# Immutable result of a shell-free command execution
|
|
29
|
+
class Result
|
|
30
|
+
attr_reader :stdout, :stderr, :exit_status
|
|
31
|
+
|
|
32
|
+
# @param stdout [String] standard output from the command
|
|
33
|
+
# @param stderr [String] standard error from the command
|
|
34
|
+
# @param exit_status [Integer] exit status code
|
|
35
|
+
def initialize(stdout:, stderr:, exit_status:)
|
|
36
|
+
@stdout = stdout.to_s.freeze
|
|
37
|
+
@stderr = stderr.to_s.freeze
|
|
38
|
+
@exit_status = exit_status || 1
|
|
39
|
+
freeze
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @return [Boolean] true if exit_status is 0
|
|
43
|
+
def success?
|
|
44
|
+
@exit_status.zero?
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Combined output, equivalent to shell `2>&1` redirection
|
|
48
|
+
# @return [String]
|
|
49
|
+
def output
|
|
50
|
+
[@stdout, @stderr].reject(&:empty?).join("\n")
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
28
54
|
# Run a command and capture its output
|
|
29
55
|
#
|
|
30
56
|
# @param command [String] The shell command to run
|
|
@@ -33,11 +59,19 @@ module Aidp
|
|
|
33
59
|
`#{command}`
|
|
34
60
|
end
|
|
35
61
|
|
|
36
|
-
#
|
|
62
|
+
# Run a command without shell interpretation and capture its output
|
|
63
|
+
#
|
|
64
|
+
# The command and its arguments are passed directly to the operating
|
|
65
|
+
# system, so shell metacharacters in any argument are treated as
|
|
66
|
+
# literal data. Prefer this over #run whenever an argument may contain
|
|
67
|
+
# externally supplied values.
|
|
37
68
|
#
|
|
38
|
-
# @
|
|
39
|
-
|
|
40
|
-
|
|
69
|
+
# @param command [Array<String>] the command and its arguments
|
|
70
|
+
# @return [Result] captured stdout/stderr with the exit status
|
|
71
|
+
def run_argv(*command)
|
|
72
|
+
require "open3"
|
|
73
|
+
stdout, stderr, status = Open3.capture3(*command.map(&:to_s))
|
|
74
|
+
Result.new(stdout: stdout, stderr: stderr, exit_status: status.exitstatus)
|
|
41
75
|
end
|
|
42
76
|
|
|
43
77
|
# Run a command via system(), optionally suppressing output
|
data/lib/aidp/version.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require "open3"
|
|
1
2
|
require "aidp/watch/base_processor"
|
|
2
3
|
require "aidp/worktree"
|
|
3
4
|
require "aidp/pr_worktree_manager"
|
|
@@ -116,11 +117,12 @@ module Aidp
|
|
|
116
117
|
# Use PRWorktreeManager's method to perform rebase and conflict resolution
|
|
117
118
|
with_worktree_context(worktree_path) do
|
|
118
119
|
# Fetch the latest changes
|
|
119
|
-
@shell_executor.system("git fetch origin")
|
|
120
|
+
@shell_executor.system("git", "fetch", "origin")
|
|
120
121
|
|
|
121
|
-
# Attempt to rebase
|
|
122
|
-
|
|
123
|
-
|
|
122
|
+
# Attempt to rebase. Pass args as separate argv entries (not an
|
|
123
|
+
# interpolated shell string) so branch names can never be
|
|
124
|
+
# interpreted by a shell.
|
|
125
|
+
rebase_output = @shell_executor.system("git", "rebase", "origin/#{base_branch}")
|
|
124
126
|
|
|
125
127
|
unless rebase_output
|
|
126
128
|
# Conflict resolution using AI
|
|
@@ -134,9 +136,8 @@ module Aidp
|
|
|
134
136
|
if resolution
|
|
135
137
|
# Stage resolved files and continue rebase
|
|
136
138
|
# GIT_EDITOR=true prevents editor from opening during automated rebase
|
|
137
|
-
|
|
138
|
-
@shell_executor.system("
|
|
139
|
-
@shell_executor.system({"GIT_EDITOR" => "true"}, "git rebase --continue")
|
|
139
|
+
@shell_executor.system("git", "add", *conflict_files)
|
|
140
|
+
@shell_executor.system({"GIT_EDITOR" => "true"}, "git", "rebase", "--continue")
|
|
140
141
|
else
|
|
141
142
|
return false
|
|
142
143
|
end
|
|
@@ -147,15 +148,19 @@ module Aidp
|
|
|
147
148
|
end
|
|
148
149
|
|
|
149
150
|
# Push the rebased branch
|
|
150
|
-
@shell_executor.system("git push -f origin
|
|
151
|
+
@shell_executor.system("git", "push", "-f", "origin", head_branch)
|
|
151
152
|
end
|
|
152
153
|
|
|
153
154
|
true
|
|
154
155
|
end
|
|
155
156
|
|
|
156
157
|
def detect_conflicting_files(worktree_path)
|
|
157
|
-
# Use git to list conflicting files
|
|
158
|
-
|
|
158
|
+
# Use git to list conflicting files. Argv form avoids shell
|
|
159
|
+
# interpretation of worktree_path or any file names in the output.
|
|
160
|
+
stdout, _stderr, _status = Dir.chdir(worktree_path) do
|
|
161
|
+
Open3.capture3("git", "diff", "--name-only", "--diff-filter=U")
|
|
162
|
+
end
|
|
163
|
+
stdout.split("\n")
|
|
159
164
|
end
|
|
160
165
|
|
|
161
166
|
def resolve_conflicts(worktree_path, base_branch, conflict_files)
|
|
@@ -189,8 +194,10 @@ module Aidp
|
|
|
189
194
|
|
|
190
195
|
# Stage and continue rebase
|
|
191
196
|
# GIT_EDITOR=true prevents editor from opening during automated rebase
|
|
192
|
-
|
|
193
|
-
|
|
197
|
+
Dir.chdir(worktree_path) do
|
|
198
|
+
@shell_executor.system("git", "add", ".")
|
|
199
|
+
@shell_executor.system({"GIT_EDITOR" => "true"}, "git", "rebase", "--continue")
|
|
200
|
+
end
|
|
194
201
|
end
|
|
195
202
|
|
|
196
203
|
def post_rebase_status(pr_number, rebase_result, error_detail = nil)
|