Skip to content

Commit

Permalink
feat(commands): add timeout to git operations
Browse files Browse the repository at this point in the history
ensures we gracefully recover from errors
  • Loading branch information
stakach committed May 13, 2022
1 parent 341138a commit f5cf9a3
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 4 deletions.
2 changes: 1 addition & 1 deletion shard.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: git-repository
version: 1.0.2
version: 1.1.0

development_dependencies:
ameba:
Expand Down
36 changes: 33 additions & 3 deletions src/git-repository/commands.cr
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,45 @@ struct GitRepository::Commands
}.to_a
end

def run_git(command : String, args : Enumerable)
def run_git(command : String, args : Enumerable, timeout : Time::Span = 5.minutes)
stdout = IO::Memory.new
git_args = [
"--no-pager",
"-C", path,
command,
].concat(args)
success = Process.new("git", git_args, output: stdout, error: stdout).wait.success?
raise GitCommandError.new("filed to git #{command}\n#{stdout}") unless success

result = Channel(Bool).new(1)
process_launched = Channel(Process?).new(1)
spawn do
begin
Process.run(
"git", git_args,
output: stdout,
error: stdout,
input: Process::Redirect::Close,
) do |process|
process_launched.send(process)
end
status = $?
result.send(status.success?)
rescue error
process_launched.send(nil)
end
end

if process = process_launched.receive
select
when success = result.receive
raise GitCommandError.new("failed to git #{command}\n#{stdout}") unless success
when timeout(timeout)
process.terminate
raise IO::TimeoutError.new("git operation took too long\n#{stdout}")
end
else
raise "failed to launch git process"
end

stdout
end
end

0 comments on commit f5cf9a3

Please sign in to comment.