[前][次][番号順一覧][スレッド一覧]

ruby-changes:57215

From: Takashi <ko1@a...>
Date: Thu, 22 Aug 2019 21:30:19 +0900 (JST)
Subject: [ruby-changes:57215] Takashi Kokubun: 15eaedf805 (master): Add misc/expand_tabs.rb ported from auto-style.rb

https://git.ruby-lang.org/ruby.git/commit/?id=15eaedf805

From 15eaedf805fb2727c79a6c59af6d5f6c2a6d634b Mon Sep 17 00:00:00 2001
From: Takashi Kokubun <takashikkbn@g...>
Date: Thu, 22 Aug 2019 21:13:34 +0900
Subject: Add misc/expand_tabs.rb ported from auto-style.rb

This is implemented to close [Misc #16112] because all other options got
at least one objection, and nobody has objected to this solution.

This code is a little complicated for the purpose, but that's just
because it includes some historical code for auto-style.rb:
https://github.com/ruby/ruby-commit-hook/blob/918a7c31b69ad2f7b125608c1c6a1f4fd01ec15a/bin/auto-style.rb

Please feel free to improve this file as you like.

[Misc #16112]

diff --git a/misc/expand_tabs.rb b/misc/expand_tabs.rb
new file mode 100755
index 0000000..c3c55ab
--- /dev/null
+++ b/misc/expand_tabs.rb
@@ -0,0 +1,171 @@ https://github.com/ruby/ruby/blob/trunk/misc/expand_tabs.rb#L1
+#!/usr/bin/env ruby --disable-gems
+# Add the following line to your `.git/hooks/pre-commit`:
+#
+#   $ ruby --disable-gems misc/expand_tabs.rb
+#
+
+require 'shellwords'
+require 'tmpdir'
+ENV['LC_ALL'] = 'C'
+
+class Git
+  def initialize(oldrev, newrev)
+    @oldrev = oldrev
+    @newrev = newrev
+  end
+
+  # ["foo/bar.c", "baz.h", ...]
+  def updated_paths
+    with_clean_env do
+      IO.popen(['git', 'diff', '--cached', '--name-only', @newrev], &:readlines).each(&:chomp!)
+    end
+  end
+
+  # [0, 1, 4, ...]
+  def updated_lines(file)
+    lines = []
+    revs_pattern = /\A0{40} /
+    with_clean_env { IO.popen(['git', 'blame', '-l', '--', file], &:readlines) }.each_with_index do |line, index|
+      if revs_pattern =~ line
+        lines << index
+      end
+    end
+    lines
+  end
+
+  def add(file)
+    git('add', file)
+  end
+
+  def toplevel
+    IO.popen(['git', 'rev-parse', '--show-toplevel'], &:read).chomp
+  end
+
+  private
+
+  def git(*args)
+    cmd = ['git', *args].shelljoin
+    unless with_clean_env { system(cmd) }
+      abort "Failed to run: #{cmd}"
+    end
+  end
+
+  def with_clean_env
+    git_dir = ENV.delete('GIT_DIR') # this overcomes '-C' or pwd
+    yield
+  ensure
+    ENV['GIT_DIR'] = git_dir if git_dir
+  end
+end
+
+DEFAULT_GEM_LIBS = %w[
+  bundler
+  cmath
+  csv
+  e2mmap
+  fileutils
+  forwardable
+  ipaddr
+  irb
+  logger
+  matrix
+  mutex_m
+  ostruct
+  prime
+  racc
+  rdoc
+  rexml
+  rss
+  scanf
+  shell
+  sync
+  thwait
+  tracer
+  webrick
+]
+
+DEFAULT_GEM_EXTS = %w[
+  bigdecimal
+  date
+  dbm
+  etc
+  fcntl
+  fiddle
+  gdbm
+  io/console
+  json
+  openssl
+  psych
+  sdbm
+  stringio
+  strscan
+  zlib
+]
+
+EXPANDTAB_IGNORED_FILES = [
+  # default gems whose master is GitHub
+  %r{\Abin/(?!erb)\w+\z},
+  *DEFAULT_GEM_LIBS.flat_map { |lib|
+    [
+      %r{\Alib/#{lib}/},
+      %r{\Alib/#{lib}\.gemspec\z},
+      %r{\Alib/#{lib}\.rb\z},
+      %r{\Atest/#{lib}/},
+    ]
+  },
+  *DEFAULT_GEM_EXTS.flat_map { |ext|
+    [
+      %r{\Aext/#{ext}/},
+      %r{\Atest/#{ext}/},
+    ]
+  },
+
+  # vendoring (ccan)
+  %r{\Accan/},
+
+  # vendoring (onigmo)
+  %r{\Aenc/},
+  %r{\Ainclude/ruby/onigmo\.h\z},
+  %r{\Areg.+\.(c|h)\z},
+
+  # explicit or implicit `c-file-style: "linux"`
+  %r{\Aaddr2line\.c\z},
+  %r{\Amissing/},
+  %r{\Astrftime\.c\z},
+  %r{\Avsnprintf\.c\z},
+]
+
+git = Git.new('HEAD^', 'HEAD')
+
+Dir.chdir(git.toplevel) do
+  paths = git.updated_paths
+  paths.select! {|l|
+    /^\d/ !~ l and /\.bat\z/ !~ l and
+    (/\A(?:config|[Mm]akefile|GNUmakefile|README)/ =~ File.basename(l) or
+     /\A\z|\.(?:[chsy]|\d+|e?rb|tmpl|bas[eh]|z?sh|in|ma?k|def|src|trans|rdoc|ja|en|el|sed|awk|p[ly]|scm|mspec|html|)\z/ =~ File.extname(l))
+  }
+  files = paths.select {|n| File.file?(n)}
+  exit if files.empty?
+
+  files.each do |f|
+    src = File.binread(f) rescue next
+
+    expanded = false
+    updated_lines = git.updated_lines(f)
+    if !updated_lines.empty? && (f.end_with?('.c') || f.end_with?('.h') || f == 'insns.def') && EXPANDTAB_IGNORED_FILES.all? { |re| !f.match(re) }
+      src.gsub!(/^.*$/).with_index do |line, lineno|
+        if updated_lines.include?(lineno) && line.start_with?("\t") # last-committed line with hard tabs
+          expanded = true
+          line.sub(/\A\t+/) { |tabs| ' ' * (8 * tabs.length) }
+        else
+          line
+        end
+      end
+    end
+
+    if expanded
+      File.binwrite(f, src)
+      git.add(f)
+    end
+  end
+end
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]