Class: RuboCop::ChangedFiles Private
| Relationships & Source Files | |
| Inherits: | Object |
| Defined in: | lib/rubocop/changed_files.rb |
Overview
Lists the files that differ from a git revision, for --changed.
Shelling out to #git keeps RuboCop free of a version control dependency, and means the answer is exactly what git would give on the command line.
Constant Summary
-
DEFAULT_REVISION =
# File 'lib/rubocop/changed_files.rb', line 13'HEAD' -
FILESYSTEM_ENCODING =
# File 'lib/rubocop/changed_files.rb', line 14Encoding.find('filesystem')
Class Method Summary
- .new(revision = nil) ⇒ ChangedFiles constructor Internal use only
Instance Attribute Summary
- #unborn_head? ⇒ Boolean readonly private Internal use only
Instance Method Summary
-
#paths ⇒ Set<String>
Internal use only
Files that were added or modified since the revision, as absolute paths.
-
#filesystem_path(path)
private
Internal use only
git hands back bytes, which Ruby tags with the encoding the process happens to have been started in - splitting those bytes as US-ASCII raises on any path that is not.
- #git(*args) private Internal use only
- #git_error_message(stderr) private Internal use only
- #modified_paths private Internal use only
- #repository_root private Internal use only
-
#split_paths(output)
private
Internal use only
The
-zabove is what makes these usable: without it git wraps any path that is not plain ASCII in quotes and octal escapes, and those files drop out of the comparison without a word. - #untracked_paths private Internal use only
Constructor Details
.new(revision = nil) ⇒ ChangedFiles
# File 'lib/rubocop/changed_files.rb', line 16
def initialize(revision = nil) @revision = revision || DEFAULT_REVISION end
Instance Attribute Details
#unborn_head? ⇒ Boolean (readonly, private)
# File 'lib/rubocop/changed_files.rb', line 53
def unborn_head? return false unless @revision == DEFAULT_REVISION _stdout, _stderr, status = Open3.capture3('git', 'rev-parse', '--verify', '--quiet', 'HEAD') !status.success? end
Instance Method Details
#filesystem_path(path) (private)
git hands back bytes, which Ruby tags with the encoding the process
happens to have been started in - splitting those bytes as US-ASCII raises
on any path that is not. They have to end up in the encoding Dir.glob
uses, or a path with a non-ASCII character in it never matches the file
list it is compared against.
On POSIX those bytes are already the filesystem’s own, so the encoding is simply corrected. Windows is the exception: git converts paths to UTF-8 on the way out, while Ruby reports file names in the local code page, so the two have to be reconciled.
# File 'lib/rubocop/changed_files.rb', line 83
def filesystem_path(path) path = path.dup return path.force_encoding(FILESYSTEM_ENCODING) unless Platform.windows? path.force_encoding(Encoding::UTF_8).encode(FILESYSTEM_ENCODING) rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError # A name the local code page cannot represent. Nothing good is left to do # with it, and dropping it would be worse than reporting it as-is. path.force_encoding(FILESYSTEM_ENCODING) end
#git(*args) (private)
[ GitHub ]#git_error_message(stderr) (private)
[ GitHub ]# File 'lib/rubocop/changed_files.rb', line 105
def (stderr) = stderr.strip = 'git failed with no output on standard error.' if .empty? "--changed could not ask git which files changed: #{}" end
#modified_paths (private)
[ GitHub ]# File 'lib/rubocop/changed_files.rb', line 38
def modified_paths # `diff.relative` would make git report paths relative to the current # directory rather than to the repository root. split_paths( git('-c', 'diff.relative=false', 'diff', '--name-only', '--diff-filter=d', '-z', @revision) ) rescue Error raise unless unborn_head? # A repository without commits has nothing to diff against, and # everything in it is untracked - which is what the caller wants to hear # rather than an error about `HEAD` not resolving. [] end
#paths ⇒ Set<String>
Files that were added or modified since the revision, as absolute paths. Deleted files are left out - there is nothing left to inspect - and untracked files are included, since a file that is new to the working tree has changed as surely as one git already knows about.
# File 'lib/rubocop/changed_files.rb', line 26
def paths root = repository_root (modified_paths + untracked_paths).to_set { |path| File.(path, root) } end
#repository_root (private)
[ GitHub ]# File 'lib/rubocop/changed_files.rb', line 34
def repository_root filesystem_path(git('rev-parse', '--show-toplevel').b.chomp) end
#split_paths(output) (private)
The -z above is what makes these usable: without it git wraps any path
that is not plain ASCII in quotes and octal escapes, and those files drop
out of the comparison without a word.
# File 'lib/rubocop/changed_files.rb', line 69
def split_paths(output) output.b.split("\0").reject(&:empty?).map { |path| filesystem_path(path) } end
#untracked_paths (private)
[ GitHub ]# File 'lib/rubocop/changed_files.rb', line 60
def untracked_paths # `--full-name` anchors the paths to the repository root, the way the # paths from `git diff` already are. split_paths(git('ls-files', '--others', '--exclude-standard', '--full-name', '-z')) end