git-diffall — 一键输出完整工作区 diff
显示原文
| #!/USR/bin/env Ruby | |
| # frozen_string_literal:真 | |
| # git-diffall - 一个列表中工作树的完整差异。 | |
| # 行为重复了bash版本;完整的帮助是持续的GitDiffAll::HELP。 | |
| 要求“open3” | |
| 模块 GitDiffAll | |
| 帮助 = <<~文本 | |
| git-diffall 是工作树的完整差异,仅有一份列表: | |
| * 跟踪文件变更(未分阶段:仅工作树 vs 索引) | |
| * 未追踪统一差分文件内容 | |
| 分阶段的变更不是输出。仓库的状态不会改变。 | |
| 使用:git diffall [--stat] [-- ...] | |
| --仅统计数据(按文件+/-) | |
| ...将输出限制在这些路径上 | |
| 所有取款均通过ONE Pager(${PAGER:-less});重定向时 | |
| To file/pipe — 寻呼器不运行,只显示纯文本。 | |
| 文本 | |
| # 求助 (-h/--求助)。 | |
| 类帮助请求<标准错误;结束 | |
| # 不是git仓库。 | |
| class NotGitRepositoryError < StandardError;结束 | |
| # 解析命令行参数。 | |
| 职业选项 | |
| attr_reader :p aths | |
| def initialize(stat: false, paths: []) | |
| @stat = 统计 | |
| @paths = 路径 | |
| 结束 | |
| 防御属性? | |
| @stat | |
| 结束 | |
| def self.parse(argv) | |
| 统计 = 错误 | |
| 路径 = [] | |
| args = argv.dup | |
| 直到 args.empty 为止? | |
| case args.shift | |
| 当“--stat”时,stat = true。 | |
| 当“-h”, “--help”时,则提出HelpRequested | |
| 当“——” | |
| paths.concat(args) | |
| args.clear(args.clear) | |
| 否则 | |
| 路径<< args.first | |
| 结束 | |
| 结束 | |
| 新(属性:属性,路径:路径) | |
| 结束 | |
| 结束 | |
| # 薄包装盖在git上:所有电话都没有自己的寻呼机,颜色都包含在内 | |
| # 强制,只有当输出通过 git 管道到达终端时才会被强制 | |
| # 关闭)。git命令的非零退出状态不是错误(diff 表示 | |
| # “存在差异”),因此不被检查,stderr 被转发到终端。 | |
| Git 类 | |
| def initialize(force_color:, stderr: $stderr) | |
| @force_color = force_color | |
| @stderr = stderr | |
| 结束 | |
| DEF 仓库? | |
| system(*base_args,'rev-parse','--git-dir',输出:File::NULL,呃:File::NULL) | |
| 结束 | |
| # 跟踪文件的变更:工作树与索引(无分阶段)。 | |
| 防御tracked_diff(路径) | |
| run('diff', *selection(paths)) | |
| 结束 | |
| def tracked_stat(路径) | |
| run('diff', '--stat', *selection(paths)) | |
| 结束 | |
| # 未追踪文件(忽略文件除外),NUL分隔符—— | |
| #适用于所有名字,包括换行。 | |
| def untracked_files(paths) | |
| out, = Open3.capture3(*base_args, 'ls-files', '--others', '--exclusion-standard', | |
| '-z', *selection(paths)) | |
| out.split(“\x0”).reject(&:empty?) | |
| 结束 | |
| # 一个未追踪文件的差异 vs. /dev/null(对于 git,它是“空文件”; | |
| # Linux上的File::NULL与“/dev/null”相同)。 | |
| def untracked_diff(路径) | |
| run('diff', '--no-index', File::NULL, path) | |
| 结束 | |
| 私人 | |
| 绝对base_args | |
| args = ['git', '--no-pager'] | |
| 如果 args.push('-c', 'color.diff=always') @force_color | |
| args | |
| 结束 | |
| DEF 选择(路径) | |
| paths.empty??[] : ['--', *路径] | |
| 结束 | |
| def run(*) | |
| stdout, stderr, = Open3.capture3(*base_args, *) | |
| @stderr.write(stderr) 除非 stderr.empty? | |
| 学生 | |
| 结束 | |
| 结束 | |
| # 输出的“正体”:跟踪文件部分 + 未跟踪文件部分。 | |
| # 子类指定各节的内容和分隔符(模板方法)。 | |
| 车级体 | |
| def initialize(git:, paths:) | |
| @git = git | |
| @paths = 路径 | |
| 结束 | |
| def渲染 | |
| ([tracked_section] + untracked_sections).join(分隔符) + 终结符 | |
| 结束 | |
| 私人 | |
| def分隔符 | |
| '' | |
| 结束 | |
| # 整个输出的尾串(DiffBody 为空)。 | |
| 《终结者》 | |
| '' | |
| 结束 | |
| 绝对tracked_section | |
| 提高 NotImplementedError | |
| 结束 | |
| 绝对untracked_sections | |
| 提高 NotImplementedError | |
| 结束 | |
| 结束 | |
| # 全差值:git diff + 每个未追踪文件一个统一差值。 | |
| 类 DiffBody < Body | |
| 私人 | |
| 绝对tracked_section | |
| @git.tracked_diff(@paths) | |
| 结束 | |
| 绝对untracked_sections | |
| @git.untracked_files(@paths).map { |file| @git.untracked_diff(file) } | |
| 结束 | |
| 结束 | |
| # 统计:git diff --stat + 未追踪文件的行计数器。 | |
| # 段 — 无尾线线的字符串:分隔符和终止符 | |
| # 将“拼接”设置得完全像 bash(printf 加 \n + 回声)。 | |
| 类别 StatBody < Body | |
| 私人 | |
| def分隔符 | |
| “\n” | |
| 结束 | |
| 《终结者》 | |
| “\n” | |
| 结束 | |
| 绝对tracked_section | |
| @git.tracked_stat(@paths) | |
| 结束 | |
| 绝对untracked_sections | |
| @git.untracked_files(@paths).map do |file| | |
| format(' %s | %d ++++', file: file, count: line_count(file)) | |
| 结束 | |
| 结束 | |
| def line_count(文件) | |
| File.foreach(file).count | |
| 结束 | |
| 结束 | |
| # 整个撤退时间只需一页;当重定向到文件/管道时,它不会启动。 | |
| 模块寻呼器 | |
| 延伸自我 | |
| 绝对是互动式的吗? | |
| $stdout.tty? | |
| 结束 | |
| 防御指挥 | |
| 寻呼机 = ENV['GIT_PAGER'] ||ENV['寻呼'] ||“更少” | |
| 寻呼机 == '更少'?“less -FRX”:寻呼机 | |
| 结束 | |
| def write(output) | |
| IO.popen(命令,'w') { |io| io.write(output) } | |
| 救援 Errno::EPIPE,Errno::ENOENT,Errno::EACCES | |
| # 寻呼机提前关闭(q)或未找到——如bash '||“正确”, | |
| # 这不是虫子。 | |
| 结束 | |
| 结束 | |
| # 编排:仓库验证、参数解析、输出收集、分页器。 | |
| 类CLI | |
| def initialize(argv,标准:$stdout,stderr:$stderr) | |
| @argv = argv | |
| @stdout = 学生 | |
| @stderr = stderr | |
| 结束 | |
| def run(防御奔跑) | |
| git =Git.new(force_color:Pager.interactive?) | |
| 除非git.repository,否则会提出NotGitRepositoryError吗? | |
| options = options.parse(@argv) | |
| 正文 = if options.stat? | |
| StatBody.new(git:git,paths: options.paths) | |
| 否则 | |
| DiffBody.new(git:git,paths: options.paths) | |
| 结束 | |
| 如果 Pager.interactive? | |
| Pager.write(body.render) | |
| 否则 | |
| @stdout.write(body.render) | |
| 结束 | |
| 0 | |
| 救援请求帮助 | |
| @stdout.write(帮助) | |
| 0 | |
| rescue NotGitRepositoryError | |
| @stderr.puts('git-diffall: не git-репозиторий') | |
| 1 | |
| 结束 | |
| 结束 | |
| 结束 | |
| # 脚本在Rails应用之外,因此此处退出为合适。 | |
| 退出 GitDiffAll::CLI.new(ARGV).run # rubocop:disable Rails/Exit |
评论
?
参与讨论