Skip to content

Change how the git CLI subprocess is executed - #684

Merged
jcouball merged 1 commit into
masterfrom
refactor_subprocess2
Jan 15, 2024
Merged

Change how the git CLI subprocess is executed#684
jcouball merged 1 commit into
masterfrom
refactor_subprocess2

Conversation

@jcouball

@jcouballjcouball commented Jan 14, 2024

Copy link
Copy Markdown
Member

Your checklist for this pull request

🚨Please review the guidelines for contributing to this repository.

  • Ensure all commits include DCO sign-off.
  • Ensure that your contributions pass unit testing.
  • Ensure that your contributions contain documentation if applicable.

TODO

Issue #687 was opened to track that this gem does not work on JRuby for Windows when using JDK > 8. This PR will be merged without this issue being solved.

Waiting for the following issues to be addressed:

Description

Fixes the following issues:

In the current implementation, all calls to git are done using backticks which has several disadvantages:

  • STDOUT and STDERR are commingled (via redirection added to the command line using 2>&1) which can cause processing errors.
  • Changes to the environment's subprocess have to be global which could impact users of this gem
  • Arguments passed on the command line go through the system shell making it difficult to escape args correctly for all platforms AND leaving this gem open to security vulnerabilities

Requirements

Implement a cross platform (Windows, Linux, and Mac) and cross Ruby (MRI, JRuby, and TruffleRuby) solution that meets the following requirements:

  1. Independently capture STDOUT and STDERR
  2. Be able to both capture STDOUT and STDIN as well as stream them to the terminal and a file at the same time if desired (e.g. for debugging)
  3. Provide a isolated environment and current working directory for the git command subprocess that does not change these global variables in the process that this gem is running in
  4. Pass command line args to the git command without being interpreted by the system shell
  5. Be able to implement a timeout on git subprocesses so they do not hang forever if input is asked for

Alternative Implementations Examined

#OptionProsCons
1Kernel.` (aka backtick)Very simpleDoes not implement any of the desired reqs
2IO.popenSimpleDoes not implement desired reqs 1, 2, 5
3Open3.popen3SimpleDoes not implement desired reqs 2 and 5
4Open3.capture3SimpleDoes not implement desired reqs 2 and 5
5Process.spawnCan be made to implement all reqsVery complex implementation
6ProcessExecuter.spawnMuch less complex than Process.spawn. Implements all reqs.Bespoke wrapper around Process.spawn. Less used in the field than other options.

Option 6 was chosen because it is the least complex implementation that implements all the requirements.

Changes Made in this PR

This PR re-implements Git::Lib#command. In order to get the desired results, some changes were needed to the signature of this method which caused some changes in code and tests.

The implementation of Git::Lib#command is handled by the new class Git::CommandLine. This class has a small interface: #initialize which accepts attribute values that do not change between git command invocations (env, binary_path, global_opts, and logger) and #run which takes the git command args, redirection, and flags for normalization, chomping, and merging stderr with stdout.

@jcouball
jcouballforce-pushed the refactor_subprocess2 branch 12 times, most recently from 7321c6f to 44a04c5CompareJanuary 15, 2024 16:57
Signed-off-by: James Couball <jcouball@yahoo.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@jcouball