git-gsub 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e4bb2c9e366b42ad834a11590b47beebf6d866b1
4
- data.tar.gz: 12fa7b4d29e60e241eaf46e7f7f0f56016a5902b
3
+ metadata.gz: 83807335e80f98fadabfb3952e2791973f3402fc
4
+ data.tar.gz: 8cb9229c0bfdc60b580fafc80269424f33fe041c
5
5
  SHA512:
6
- metadata.gz: 91991a9c7329b9dcb883c5270577fa7779bb6a6f680dfd840aacdcac00fc79745a58a6c55744f2e1cad730fa39ddf6fc8e30876fbe4ad896b43b48cf852233b8
7
- data.tar.gz: 4b3e90f5d4706c5a47720f49448ee1f5cae3ac19af372b5f612add9507855ac31af1c2476a1432002d4020dfd3757a0af05e7484569db112ceef659d975c3b00
6
+ metadata.gz: 6e26c83eb04af98873ef2b479f408eea7b29ee997ac38a835cb58f918a3c1a3f4924f8238b2f9d03de000e71247104276265c400ab7a41b8a8de589e165f83a0
7
+ data.tar.gz: 806e3d07a225082419864df8fd74a1dc3d0b0aa37c47f6363c93a27298e874b826efe16fe39a2acffba8ec49e95f362306dd0eaec98e853261c779710a9e3a0f
@@ -1,5 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1.0
4
- - 2.1.1
5
- - 2.1.2
3
+ - 2.1
4
+ - 2.2
5
+ - 2.3
6
+ - 2.4
@@ -1,6 +1,14 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [0.0.6]
5
+ ### Added
6
+ - Add option to substitute in camel/kebab/snake case
7
+ - Add option to rename files
8
+ ### Changed
9
+ - Do substitution with Perl, not sed to reduce platform issues
10
+ - No escape required to command line arguments
11
+
4
12
  ## [0.0.5] - 2017-05-23
5
13
  ### Fixed
6
14
  - Fix bug on assigning target directories
data/README.md CHANGED
@@ -4,13 +4,25 @@ A Git subcommand to do gsub in a repository
4
4
 
5
5
  ## Usage
6
6
 
7
- To substitute `Git` with `Subversion`, run
7
+ ```
8
+ Usage: git gsub [options] FROM TO [PATHS]
9
+ -v, --version Print version
10
+ --snake Experimental: substitute snake-cased expressions
11
+ --camel Experimental: substitute camel-cased expressions
12
+ --kebab Experimental: substitute kebab-cased expressions
13
+ --rename Rename files along with substitution
14
+ --dry-run Print commands to be run
15
+ ```
16
+
17
+ ## Example
18
+
19
+ To substitute `Git` with `Subversion`:
8
20
 
9
21
  ```
10
22
  $ git gsub Git Subversion
11
23
  ```
12
24
 
13
- Then you will get
25
+ Result:
14
26
 
15
27
  ```diff
16
28
  diff --git a/README.md b/README.md
@@ -35,25 +47,74 @@ index c30f093..03b7c4c 100755
35
47
  +Subversion::Gsub.run
36
48
  ```
37
49
 
38
- ## Installation
50
+ ## Experimental features
51
+ To substitute `CommonLisp` with `VisualBasic` with case-awareness:
39
52
 
40
53
  ```
41
- $ gem install git-gsub
54
+ $ git gsub CommonLisp VisualBasic --kebab --snake --camel
55
+ ```
56
+
57
+ Result:
58
+
59
+ ```diff
60
+ diff --git a/README.md b/README.md
61
+ index 2185dbf..393dbc6 100644
62
+ --- a/README.md
63
+ +++ b/README.md
64
+ @@ -1,4 +1,4 @@
65
+ -# CommonLisp common_lisp common-lisp
66
+ +# VisualBasic visual_basic visual-basic
67
+ ```
68
+
69
+ Substitute and rename file:
70
+
42
71
  ```
72
+ $ git gsub ruby haskell --rename --camel
73
+ ```
74
+
75
+ Result:
43
76
 
44
- ## Escaping special characters
77
+ ```diff
78
+ diff --git a/haskell.hs b/haskell.hs
79
+ new file mode 100644
80
+ index 0000000..ae86ce3
81
+ --- /dev/null
82
+ +++ b/haskell.hs
83
+ @@ -0,0 +1 @@
84
+ +putStrLn "Haskell"
85
+ diff --git a/haskell.rb b/haskell.rb
86
+ new file mode 100644
87
+ index 0000000..9f363d3
88
+ --- /dev/null
89
+ +++ b/haskell.rb
90
+ @@ -0,0 +1 @@
91
+ +puts "haskell"
92
+ diff --git a/ruby.hs b/ruby.hs
93
+ deleted file mode 100644
94
+ index 70db14d..0000000
95
+ --- a/ruby.hs
96
+ +++ /dev/null
97
+ @@ -1 +0,0 @@
98
+ -putStrLn "Ruby"
99
+ diff --git a/ruby.rb b/ruby.rb
100
+ deleted file mode 100644
101
+ index 966eb68..0000000
102
+ --- a/ruby.rb
103
+ +++ /dev/null
104
+ @@ -1 +0,0 @@
105
+ ```
45
106
 
46
- `git-gsub` uses `sed` internally, so escaping is same as it.
107
+ Caution: Case conversion is done with [ActiveSupport/Inflector](http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html) , which substitutes `::` with `/`. This may cause unexpected result in the language other than Ruby.
47
108
 
48
- If you want to replace `git/gsub` with `svn/gsub`, the command will be
109
+ ## Installation
49
110
 
50
111
  ```
51
- $ git gsub "git\/gsub" "svn\/gsub"
112
+ $ gem install git-gsub
52
113
  ```
53
114
 
54
115
  ## Supported platforms
55
116
 
56
- Maybe on many *nix like OS which has sed/gsed.
117
+ Maybe on many *nix like OS which has Perl and sed.
57
118
 
58
119
  ## Contributing
59
120
 
@@ -1,4 +1,4 @@
1
1
  #! /usr/bin/env ruby
2
2
 
3
3
  require 'git/gsub'
4
- Git::Gsub.run
4
+ Git::Gsub.run(ARGV)
@@ -16,6 +16,7 @@ Gem::Specification.new do |spec|
16
16
  spec.files = `git ls-files -z`.split("\x0")
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.add_dependency "activesupport", "~> 4"
19
20
  spec.require_paths = ["lib"]
20
21
 
21
22
  spec.add_development_dependency "bundler", "~> 1.5"
@@ -1,14 +1,63 @@
1
- require "git/gsub/version"
1
+ require 'git/gsub/version'
2
+ require 'active_support/inflector'
3
+ require 'optparse'
2
4
  require 'shellwords'
5
+ require 'English'
3
6
 
4
7
  module Git
5
8
  module Gsub
6
- def self.run
7
- case ARGV.first
8
- when '-v', '--version'
9
+ def self.run(argv)
10
+ opts = OptionParser.new
11
+
12
+ self.class.module_eval do
13
+ define_method(:usage) do |msg = nil|
14
+ puts opts.to_s
15
+ puts "error: #{msg}" if msg
16
+ exit 1
17
+ end
18
+ end
19
+
20
+ options = {}
21
+ opts.on('-v', '--version', 'Print version') do |_v|
22
+ options[:version] = true
23
+ end
24
+
25
+ opts.on('--snake', 'Experimental: substitute snake-cased expressions') do |_v|
26
+ options[:snake] = true
27
+ end
28
+
29
+ opts.on('--camel', 'Experimental: substitute camel-cased expressions') do |_v|
30
+ options[:camel] = true
31
+ end
32
+
33
+ opts.on('--kebab', 'Experimental: substitute kebab-cased expressions') do |_v|
34
+ options[:kebab] = true
35
+ end
36
+
37
+ opts.on('--rename', 'Rename files along with substitution') do |_v|
38
+ options[:rename] = true
39
+ end
40
+
41
+ opts.on('--dry-run', 'Print commands to be run') do |_v|
42
+ options[:dry] = true
43
+ end
44
+
45
+ opts.banner = 'Usage: git gsub [options] FROM TO [PATHS]'
46
+
47
+ begin
48
+ args = opts.parse(argv)
49
+ rescue OptionParser::InvalidOption => e
50
+ usage e.message
51
+ end
52
+
53
+ if options[:version]
9
54
  version
10
55
  else
11
- gsub *ARGV
56
+ from, to, *paths = args
57
+ usage 'No FROM given' unless from
58
+ usage 'No TO given' unless to
59
+ Commands::Gsub.new(from, to, paths, options).run
60
+ Commands::Rename.new(from, to, paths, options).run if options[:rename]
12
61
  end
13
62
  end
14
63
 
@@ -16,29 +65,64 @@ module Git
16
65
  puts Git::Gsub::VERSION
17
66
  end
18
67
 
19
- def self.gsub *args
20
- from, to, *paths = args.map do |arg|
21
- Shellwords.escape arg if arg
22
- end
68
+ module Commands
69
+ class Command
70
+ attr_accessor :from, :to, :paths, :options
71
+
72
+ def initialize(from, to, paths = [], options = {})
73
+ @from = from
74
+ @to = to
75
+ @paths = paths
76
+ @options = options
77
+ end
78
+
79
+ def run_commands(commands)
80
+ if options[:dry]
81
+ commands.each { |c| puts c }
82
+ else
83
+ commands.each { |c| system c }
84
+ end
85
+ end
23
86
 
24
- if to.nil?
25
- abort "No argument to gsub was given"
87
+ def args
88
+ args = []
89
+ args << [from, to]
90
+ args << [from.camelcase, to.camelcase] if options[:camel]
91
+ args << [from.underscore, to.underscore] if options[:snake]
92
+ args << [from.underscore.dasherize, to.underscore.dasherize] if options[:kebab]
93
+
94
+ args.compact
95
+ end
26
96
  end
27
97
 
28
- target_files = (`git grep -l #{from} #{paths.join ' '}`).each_line.map(&:chomp).join ' '
98
+ class Gsub < Command
99
+ def run
100
+ commands = args.map { |from, to| build_command(from, to, paths) }.compact
101
+ run_commands commands
102
+ end
29
103
 
30
- if system_support_gsed?
31
- system %|gsed -i s/#{from}/#{to}/g #{target_files}|
32
- else
33
- system %|sed -i "" -e s/#{from}/#{to}/g #{target_files}|
104
+ def build_command(from, to, paths = [], _options = {})
105
+ from, to, *paths = [from, to, *paths].map { |s| Shellwords.escape s }
106
+
107
+ target_files = `git grep -l #{from} #{paths.join ' '}`.each_line.map(&:chomp).join ' '
108
+ return if target_files.empty?
109
+
110
+ %(perl -pi -e 's{#{from}}{#{to}}g' #{target_files})
111
+ end
34
112
  end
35
- end
36
113
 
37
- private
114
+ class Rename < Command
115
+ def run
116
+ commands = args.map { |from, to| build_command(from, to, paths) }
117
+ run_commands commands
118
+ end
119
+
120
+ def build_command(from, to, paths = [], _options = {})
121
+ from, to, *paths = [from, to, *paths].map { |s| Shellwords.escape s }
38
122
 
39
- def self.system_support_gsed?
40
- `which gsed`
41
- $?.success?
123
+ %[for f in $(git ls-files #{paths.join ' '} | grep #{from}); do mkdir -p $(dirname $(echo $f | sed 's/#{from}/#{to}/g')); git mv $f $(echo $f | sed 's/#{from}/#{to}/g') 2>/dev/null; done]
124
+ end
125
+ end
42
126
  end
43
127
  end
44
128
  end
@@ -1,5 +1,5 @@
1
1
  module Git
2
2
  module Gsub
3
- VERSION = "0.0.5"
3
+ VERSION = '0.0.6'.freeze
4
4
  end
5
5
  end
@@ -4,51 +4,79 @@ require 'git/gsub'
4
4
  require 'pry'
5
5
 
6
6
  describe 'git-gsub' do
7
- def run_in_directory_with_a_file content
7
+ def run_in_directory_with_a_file(filename, content)
8
8
  Dir.mktmpdir do |dir|
9
- filename = "FOO"
10
9
  Dir.chdir dir do
10
+ dirname = File.dirname(filename)
11
+ FileUtils.mkdir_p(dirname) unless File.exists?(dirname)
11
12
  File.open(filename, 'w') { |f| f << content }
12
13
  `git init`
13
14
  `git config --local user.email "you@example.com"`
14
15
  `git config --local user.name "Your Name"`
15
16
  `git add .`
16
17
  `git commit -m init`
17
- yield filename
18
+ yield
18
19
  end
19
20
  end
20
21
  end
21
22
 
22
23
  it 'should substitute files' do
23
- run_in_directory_with_a_file "Git Subversion Bzr" do |filename|
24
- Git::Gsub.gsub "Bzr", "Mercurial"
25
- file = File.read(filename).chomp
26
- expect(file).to eq "Git Subversion Mercurial"
24
+ run_in_directory_with_a_file 'README.md', 'Git Subversion Bzr' do
25
+ Git::Gsub.run %w[Bzr Mercurial]
26
+ expect(File.read('README.md')).to eq 'Git Subversion Mercurial'
27
27
  end
28
28
  end
29
29
 
30
- it 'should escape well' do
31
- run_in_directory_with_a_file %|<h1 class="foo">| do |filename|
32
- Git::Gsub.gsub %|<h1 class="foo">|, %|<h1 class="bar">|
33
- file = File.read(filename).chomp
34
- expect(file).to eq %|<h1 class="bar">|
30
+ it 'should substitute files with case conversion' do
31
+ run_in_directory_with_a_file 'README.md', 'GitGsub git_gsub git-gsub' do
32
+ Git::Gsub.run %w[GitGsub SvnGsub --camel --kebab --snake]
33
+ expect(File.read('README.md')).to eq 'SvnGsub svn_gsub svn-gsub'
35
34
  end
36
35
  end
37
36
 
38
- it 'should raise error if second argument wasn\'t given' do
39
- run_in_directory_with_a_file "Git Subversion Bzr" do |filename|
40
- begin
41
- Git::Gsub.gsub "Bzr"
42
- rescue SystemExit => e
43
- expect(e.message).to match /No argument/
44
- end
37
+ it 'should escape well' do
38
+ run_in_directory_with_a_file 'README.md', %(<h1 class="foo">) do
39
+ Git::Gsub.run [%(<h1 class="foo">), %(<h1 class="bar">)]
40
+ expect(File.read('README.md')).to eq %(<h1 class="bar">)
41
+ end
42
+
43
+ run_in_directory_with_a_file 'README.md', %(git/gsub) do
44
+ Git::Gsub.run [%(git/gsub), %(svn/sub)]
45
+ expect(File.read('README.md')).to eq %(svn/sub)
46
+ end
47
+
48
+ run_in_directory_with_a_file 'README.md', %({git{svn}) do
49
+ Git::Gsub.run [%({git{svn}), %({hg{svn})]
50
+ expect(File.read('README.md')).to eq %({hg{svn})
45
51
  end
46
52
  end
47
53
 
48
54
  it 'should not create backup file' do
49
- run_in_directory_with_a_file "Git Subversion Bzr" do |filename|
50
- Git::Gsub.gsub "Bzr", "Darcs"
51
- expect(`ls`).to eql "FOO\n"
55
+ run_in_directory_with_a_file 'README.md', 'Git Subversion Bzr' do
56
+ Git::Gsub.run %w[Bzr Darcs]
57
+ expect(`ls`).to eql "README.md\n"
58
+ end
59
+ end
60
+
61
+ it 'should rename with --rename' do
62
+ run_in_directory_with_a_file 'README-git_gsub.md', 'GitGsub git_gsub git-gsub' do
63
+ Git::Gsub.run %w[GitGsub SvnGsub --snake --rename]
64
+ expect(`ls`).to eql "README-svn_gsub.md\n"
65
+ expect(File.read('README-svn_gsub.md')).to eq 'SvnGsub svn_gsub git-gsub'
66
+ end
67
+
68
+ run_in_directory_with_a_file 'lib/git.rb', 'puts "Git"' do
69
+ Git::Gsub.run %w[git svn --camel --rename]
70
+ expect(`ls lib`).to eql "svn.rb\n"
71
+ expect(File.read('lib/svn.rb')).to eq 'puts "Svn"'
72
+ end
73
+ end
74
+
75
+ it 'should do nothing if no file found' do
76
+ run_in_directory_with_a_file 'README-git_gsub.md', 'GitGsub git_gsub git-gsub' do
77
+ expect {
78
+ Git::Gsub.run %w[Atlanta Chicago --snake --rename]
79
+ }.not_to raise_error
52
80
  end
53
81
  end
54
82
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git-gsub
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fujimura Daisuke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-23 00:00:00.000000000 Z
11
+ date: 2017-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement