mmve 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ff3cb10f46ee14137bfb99473ec4898d5c83acfc
4
- data.tar.gz: 9bec858348ee596b1597096a0f6d7942bd98b765
3
+ metadata.gz: e49ee8d7e9c945585397a63e8be7d6b679fd01ed
4
+ data.tar.gz: 48c4f46ea97ddb0c19fee1fe5a5ff5a7185018e9
5
5
  SHA512:
6
- metadata.gz: c8e5f51bccb5212f7e19cd204b1abc45ad6ef727bf031c0c5c95baa0127f4dcb341fa8d7dc5030a629285f8ca81558f4063aedc10270d4d7fa0d663be33e7006
7
- data.tar.gz: 4aaac79acc5a36714df8c5032979dc51cdd0c2e7a35f2e4afe4281d4bcf516b883854a55db58320ae706ac7663a0ebad7af27c9b4d0697d57f1b869ea9170f68
6
+ metadata.gz: fbdca8890eea2a45ee55f07b0edb56469e53d76b39408c8dc1ec8c188871ba6702dd29848dad2810740a702af6ea4c3e414b59b531983805daffdb945d1d51a3
7
+ data.tar.gz: 0c9aa0f41cbcc9ee4374c10584f876e1bf9049c6eaa654813f4286faeced3a0d030289c0ba85681c17415a12b107cb378ee95328cf17f2dc02102956dc188e4e
data/README.md CHANGED
@@ -2,19 +2,3 @@ MMVE
2
2
  ====
3
3
 
4
4
  Mass MV Edit: use your editor to move (rename) files.
5
-
6
-
7
- TODO
8
- ----
9
-
10
- * Recurse directories:
11
- - `-r some_dir` will rename `some_dir` entries.
12
- `somedir/` could also be used
13
- - `-rr some_dir` will rename all files found recursively in
14
- `some_dir`
15
-
16
- * Handle conflicts in edited files
17
-
18
- * Make EDITOR configurable in the API, keep ENV['EDITOR'] as default.
19
-
20
- * Sort entries
data/bin/mmve CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  require 'mmve'
4
4
 
5
- MMVE::CLI.new(ARGV).run!
5
+ MMVE::CLI.run(ARGV)
@@ -1,4 +1,13 @@
1
+ require 'baf/cli'
2
+
1
3
  require 'mmve/cli'
2
4
  require 'mmve/editor'
3
5
  require 'mmve/renamer'
4
6
  require 'mmve/version'
7
+
8
+ module MMVE
9
+ Error = Class.new StandardError
10
+ RuntimeError = Class.new Error
11
+ DestinationEntriesMismatch = Class.new RuntimeError
12
+ DestructiveRename = Class.new RuntimeError
13
+ end
@@ -1,31 +1,25 @@
1
1
  module MMVE
2
- class CLI
3
- USAGE = "Usage: #{File.basename $0} [ path ... ]".freeze
2
+ class CLI < Baf::CLI
3
+ USAGE = "Usage: #{File.basename $0} path [path ...]".freeze
4
4
 
5
- def initialize arguments, stdout = $stdout
6
- @arguments = arguments
7
- @stdout = stdout
5
+ def initialize env, arguments, **opts
6
+ super
7
+ @editor = opts[:editor] || Editor.new(ENV['EDITOR'])
8
+ @renamer = opts[:renamer] || Renamer.new
8
9
  end
9
10
 
10
- def run!
11
- print_usage_and_exit if @arguments.include? '-h'
12
- renamer.destinations = editor.edit renamer.sources
13
- renamer.execute!
11
+ def setup
12
+ banner USAGE
13
+ flag_version MMVE::VERSION
14
14
  end
15
15
 
16
- def editor
17
- @editor ||= Editor.new ENV['EDITOR']
18
- end
19
-
20
- def renamer
21
- @renamer ||= Renamer.new @arguments
16
+ def run
17
+ usage! unless arguments.any?
18
+ renamer.rename arguments, editor.edit(arguments)
22
19
  end
23
20
 
24
21
  private
25
22
 
26
- def print_usage_and_exit
27
- @stdout.puts USAGE
28
- exit
29
- end
23
+ attr_reader :editor, :renamer
30
24
  end
31
25
  end
@@ -1,17 +1,22 @@
1
1
  module MMVE
2
2
  class Renamer
3
- attr_reader :sources
4
- attr_accessor :destinations
5
-
6
- def initialize paths
7
- @sources = paths
8
- @destinations = @sources.dup
3
+ def initialize file: File
4
+ @file = file
9
5
  end
10
6
 
11
- def execute!
12
- [@sources, @destinations].transpose.each do |e|
13
- File.rename *e if e.uniq.count == 2
7
+ def rename sources, destinations
8
+ fail DestinationEntriesMismatch if sources.size != destinations.size
9
+ [sources, destinations].transpose.each do |paths|
10
+ src, dst = paths
11
+ next if src == dst
12
+ fail DestructiveRename if sources.include? dst
13
+ fail DestructiveRename if file.exist? dst
14
+ file.rename *paths
14
15
  end
15
16
  end
17
+
18
+ private
19
+
20
+ attr_reader :file
16
21
  end
17
22
  end
@@ -1,3 +1,3 @@
1
1
  module MMVE
2
- VERSION = '0.1.2'.freeze
2
+ VERSION = '0.2.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,71 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mmve
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thibault Jouan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-05 00:00:00.000000000 Z
11
+ date: 2017-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rake
14
+ name: baf
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '10.4'
20
- type: :development
19
+ version: '0.11'
20
+ type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '10.4'
26
+ version: '0.11'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rspec
28
+ name: baf-testing
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '3.2'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '3.2'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: cucumber
42
+ name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '1.3'
47
+ version: '10.4'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '1.3'
54
+ version: '10.4'
55
55
  - !ruby/object:Gem::Dependency
56
- name: aruba
56
+ name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0.6'
61
+ version: '3.2'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0.6'
68
+ version: '3.2'
69
69
  description: 'Mass MV Editor: move files with your favourite $EDITOR'
70
70
  email: tj@a13.fr
71
71
  executables:
@@ -74,32 +74,13 @@ extensions: []
74
74
  extra_rdoc_files:
75
75
  - README.md
76
76
  files:
77
- - ".gitignore"
78
- - ".rspec"
79
- - ".travis.yml"
80
- - Guardfile
81
- - LICENSE
82
77
  - README.md
83
- - Rakefile
84
78
  - bin/mmve
85
- - config/cucumber.yaml
86
- - features/rename.feature
87
- - features/step_definitions/editor_steps.rb
88
- - features/step_definitions/filesystem_steps.rb
89
- - features/support/env_aruba.rb
90
- - features/support/env_cucumber-doc_string.rb
91
- - features/usage.feature
92
79
  - lib/mmve.rb
93
80
  - lib/mmve/cli.rb
94
81
  - lib/mmve/editor.rb
95
82
  - lib/mmve/renamer.rb
96
83
  - lib/mmve/version.rb
97
- - mmve.gemspec
98
- - spec/mmve/cli_spec.rb
99
- - spec/mmve/editor_spec.rb
100
- - spec/mmve/renamer_spec.rb
101
- - spec/spec_helper.rb
102
- - spec/support/exit_helpers.rb
103
84
  homepage: https://rubygems.org/gems/mmve
104
85
  licenses:
105
86
  - BSD-3-Clause
@@ -120,8 +101,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
101
  version: '0'
121
102
  requirements: []
122
103
  rubyforge_project:
123
- rubygems_version: 2.6.10
104
+ rubygems_version: 2.6.11
124
105
  signing_key:
125
106
  specification_version: 4
126
- summary: mmve-0.1.2
107
+ summary: Mass MV Editor
127
108
  test_files: []
data/.gitignore DELETED
@@ -1 +0,0 @@
1
- /tmp/
data/.rspec DELETED
@@ -1 +0,0 @@
1
- --require spec_helper
@@ -1,42 +0,0 @@
1
- sudo: required
2
- dist: trusty
3
- language: c
4
- addons:
5
- apt:
6
- packages:
7
- - realpath
8
- notifications:
9
- email:
10
- - tj+travis_mmve@a13.fr
11
- on_success: never
12
-
13
- env:
14
- - RUBYVER=2.4-stable
15
- - RUBYVER=2.3-stable
16
- - RUBYVER=2.2-stable
17
- - RUBYVER=2.1-stable
18
- cache:
19
- directories:
20
- - ${HOME}/.gem/travis
21
- - ${HOME}/usr
22
- timeout: 3600
23
-
24
- before_install:
25
- - sudo apt-get --purge remove ruby\*
26
- - rm -rf ~/.bash*
27
- - unset gem GEM_HOME GEM_PATH RUBYOPT IRBRC
28
- - export PATH=/bin:/usr/bin RB=$HOME/usr/bin/ruby
29
- - test -x $RB || wget http://ftp.ruby-lang.org/pub/ruby/ruby-${RUBYVER}.tar.xz
30
- - test -x $RB || tar xfJ ruby-*.tar.xz
31
- - test -x $RB || cd ruby-*
32
- - test -x $RB || ./configure --prefix=$HOME/usr --disable-install-doc --with-out-ext=tk
33
- - test -x $RB || (make && make install)
34
- - echo "source 'https://rubygems.org'; gemspec" > ~/spec_deps.rb
35
- install:
36
- - unset gem GEM_HOME GEM_PATH RUBYOPT IRBRC
37
- - export GEM_HOME=~/.gem/travis GEM_PATH=~/.gem/travis
38
- - export PATH=$GEM_HOME/bin:$HOME/usr/bin:/bin:/usr/bin
39
- - cd $TRAVIS_BUILD_DIR
40
- - gem install -g ~/spec_deps.rb
41
- script:
42
- - MMVE_CI=yes RUBYOPT=-I$(realpath lib) rake
data/Guardfile DELETED
@@ -1,11 +0,0 @@
1
- guard :cucumber, cmd_additional_args: '--profile guard', all_on_start: false do
2
- watch %r{\Afeatures/.+\.feature\z}
3
- watch(%r{\Afeatures/support/.+\.rb\z}) { 'features' }
4
- watch(%r{\Afeatures/step_definitions/.+_steps\.rb\z}) { 'features' }
5
- end
6
-
7
- guard :rspec, cmd: 'rspec -f doc' do
8
- watch %r{\Aspec/.+_spec\.rb\z}
9
- watch(%r{\Alib/(.+)\.rb\z}) { |m| "spec/#{m[1]}_spec.rb" }
10
- watch('spec/spec_helper.rb') { 'spec' }
11
- end
data/LICENSE DELETED
@@ -1,30 +0,0 @@
1
- Copyright 2013 Thibault Jouan. All rights reserved.
2
-
3
- Redistribution and use in source and binary forms, with or without
4
- modification, are permitted provided that the following conditions are
5
- met:
6
-
7
- * Redistributions of source code must retain the above copyright
8
- notice, this list of conditions and the following disclaimer.
9
-
10
- * Redistributions in binary form must reproduce the above copyright
11
- notice, this list of conditions and the following disclaimer in
12
- the documentation and/or other materials provided with the
13
- distribution.
14
-
15
- * Neither the name of the software nor the names of its contributors
16
- may be used to endorse or promote products derived from this
17
- software without specific prior written permission.
18
-
19
-
20
- THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS "AS IS" AND
21
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS
24
- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27
- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28
- WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29
- OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30
- IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/Rakefile DELETED
@@ -1,11 +0,0 @@
1
- require 'cucumber/rake/task'
2
- require 'rspec/core/rake_task'
3
-
4
-
5
- task default: %i[features spec]
6
-
7
- Cucumber::Rake::Task.new :features do |t|
8
- t.profile = 'quiet' if ENV.key? 'MMVE_CI'
9
- end
10
-
11
- RSpec::Core::RakeTask.new
@@ -1,3 +0,0 @@
1
- default: --no-source
2
- guard: --format pretty --quiet
3
- quiet: --format progress
@@ -1,17 +0,0 @@
1
- Feature: Rename files
2
-
3
- Background:
4
- Given the following files exists:
5
- | some_file |
6
- | another_file |
7
-
8
- Scenario: renames files given as arguments when the editor modify file paths
9
- Given my editor is "ed"
10
- When I run `mmve some_file another_file` interactively
11
- And I type "%s/some/renamed/"
12
- And I type "wq"
13
- Then the exit status must be 0
14
- Then the following files must exist:
15
- | renamed_file |
16
- | another_file |
17
- And the file "some_file" must not exist
@@ -1,3 +0,0 @@
1
- Given /^my editor is "([^"]+)"$/ do |editor|
2
- set_environment_variable 'EDITOR', editor
3
- end
@@ -1,3 +0,0 @@
1
- Given /^the following files exists:$/ do |paths|
2
- paths.raw.flatten.each { |e| write_file e, '' }
3
- end
@@ -1,16 +0,0 @@
1
- module Cucumber
2
- class Runtime
3
- alias :old_step_match :step_match
4
-
5
- def step_match step_name, name_to_report = nil
6
- if step_name.include? ' must '
7
- name_to_report = step_name.dup
8
- step_name.gsub! ' must ', ' should '
9
- end
10
-
11
- old_step_match step_name, name_to_report
12
- end
13
- end
14
- end
15
-
16
- require 'aruba/cucumber'
@@ -1,23 +0,0 @@
1
- require 'cucumber/formatter/pretty'
2
-
3
- module Cucumber
4
- module Ast
5
- class DocString
6
- alias :old_initialize :initialize
7
-
8
- def initialize string, content_type
9
- old_initialize string + $/, content_type
10
- end
11
- end
12
- end
13
-
14
- module Formatter
15
- class Pretty
16
- alias :old_doc_string :doc_string
17
-
18
- def doc_string string
19
- old_doc_string string.chomp
20
- end
21
- end
22
- end
23
- end
@@ -1,8 +0,0 @@
1
- Feature: CLI usage
2
-
3
- Scenario: prints the usage when -h argument is given
4
- When I successfully run `mmve -h`
5
- Then the output must contain exactly:
6
- """
7
- Usage: mmve [ path ... ]
8
- """
@@ -1,23 +0,0 @@
1
- require File.expand_path('../lib/mmve/version', __FILE__)
2
-
3
- Gem::Specification.new do |s|
4
- s.name = 'mmve'
5
- s.version = MMVE::VERSION
6
- s.summary = "mmve-#{MMVE::VERSION}"
7
- s.description = 'Mass MV Editor: move files with your favourite $EDITOR'
8
- s.license = 'BSD-3-Clause'
9
- s.homepage = 'https://rubygems.org/gems/mmve'
10
-
11
- s.authors = 'Thibault Jouan'
12
- s.email = 'tj@a13.fr'
13
-
14
- s.files = `git ls-files`.split $/
15
- s.executables = 'mmve'
16
- s.extra_rdoc_files = %w[README.md]
17
-
18
-
19
- s.add_development_dependency 'rake', '~> 10.4'
20
- s.add_development_dependency 'rspec', '~> 3.2'
21
- s.add_development_dependency 'cucumber', '~> 1.3'
22
- s.add_development_dependency 'aruba', '~> 0.6'
23
- end
@@ -1,52 +0,0 @@
1
- RSpec.describe MMVE::CLI do
2
- include ExitHelpers
3
-
4
- let(:arguments) { %i[some arguments] }
5
- let(:stdout) { StringIO.new }
6
- subject(:cli) { described_class.new arguments, stdout }
7
-
8
- describe '#run!' do
9
- it 'edits the renamer source paths' do
10
- renamer = double('renamer').as_null_object
11
- allow(cli).to receive(:renamer) { renamer }
12
- expect(cli.editor)
13
- .to receive(:edit)
14
- .with cli.renamer.sources
15
- cli.run!
16
- end
17
-
18
- it 'assigns the edited source paths as the renamer destination paths' do
19
- editor = double 'editor'
20
- allow(cli).to receive(:editor) { editor }
21
- allow(editor).to receive(:edit) { arguments }
22
- expect(cli.renamer)
23
- .to receive(:destinations=)
24
- .with arguments
25
- cli.run!
26
- end
27
-
28
- it 'executes the renamer' do
29
- editor = double('editor').as_null_object
30
- allow(cli).to receive(:editor) { editor }
31
- expect(cli.renamer).to receive :execute!
32
- cli.run!
33
- end
34
-
35
- context 'when one of the arguments is -h' do
36
- let(:arguments) { %w[-h] }
37
-
38
- it 'prints the usage' do
39
- trap_exit { cli.run! }
40
- expect(stdout.string).to eq <<-eoh
41
- Usage: rspec [ path ... ]
42
- eoh
43
- end
44
-
45
- it 'exits successfully' do
46
- expect { cli.run! }.to raise_error SystemExit do |e|
47
- expect(e.status).to be 0
48
- end
49
- end
50
- end
51
- end
52
- end
@@ -1,76 +0,0 @@
1
- RSpec.describe MMVE::Editor do
2
- let(:editor_command) { 'some editor command' }
3
- subject(:editor) { described_class.new editor_command }
4
-
5
- describe '#edit' do
6
- let(:paths) { %w[some_path other_path] }
7
- let(:paths_str) { paths * $/ + $/ }
8
-
9
- it 'creates a temporary file with the paths as content' do
10
- expect(editor)
11
- .to receive(:with_temp_file)
12
- .with(paths_str)
13
- .and_return paths_str
14
- editor.edit paths
15
- end
16
-
17
- it 'sends the edit_file message with the temporary file' do
18
- expect(editor)
19
- .to receive(:edit_file)
20
- .with any_args
21
- editor.edit paths
22
- end
23
-
24
- it 'returns the edited file paths as a list' do
25
- allow(editor).to receive(:with_temp_file) { paths_str }
26
- expect(editor.edit paths).to eq paths
27
- end
28
- end
29
-
30
- describe '#with_temp_file' do
31
- let(:content) { "some_content\n" }
32
-
33
- it 'opens a temporary file' do
34
- expect(Tempfile)
35
- .to receive(:open)
36
- .with 'rspec_'
37
- editor.with_temp_file(content) { }
38
- end
39
-
40
- it 'it writes the content to the file' do
41
- file = double('file').as_null_object
42
- allow(Tempfile)
43
- .to receive(:open)
44
- .and_yield file
45
- expect(file).to receive(:write).with content
46
- editor.with_temp_file(content) { }
47
- end
48
-
49
- it 'yields the block with the file as argument' do
50
- file = double('file').as_null_object
51
- allow(Tempfile)
52
- .to receive(:open)
53
- .and_yield file
54
- expect { |b| editor.with_temp_file content, &b }
55
- .to yield_with_args file
56
- end
57
-
58
- it 'returns the temporary file content after yielding the block' do
59
- new_content = "new_content\n"
60
- expect(
61
- editor.with_temp_file(content) { |f| File.write f.path, new_content }
62
- ).to eq new_content
63
- end
64
- end
65
-
66
- describe '#edit_file' do
67
- let(:file) { double 'file', path: 'some_path' }
68
-
69
- it 'executes the editor command with the file path as argument' do
70
- expect(editor)
71
- .to receive(:system)
72
- .with *editor_command.split, file.path
73
- editor.edit_file file
74
- end
75
- end
76
- end
@@ -1,37 +0,0 @@
1
- RSpec.describe MMVE::Renamer do
2
- let(:sources) { %w[some_path other_path] }
3
- let(:destinations) { %w[renamed_path other_path] }
4
- subject(:renamer) { described_class.new sources }
5
-
6
- it 'assigns destination paths equivalent to source paths' do
7
- expect(renamer.destinations).to eq sources
8
- end
9
-
10
- it 'copies the assignated destinations paths' do
11
- expect(renamer.destinations).not_to be sources
12
- end
13
-
14
- describe '#execute!' do
15
- context 'when destinations differs from sources' do
16
- before do
17
- renamer.destinations = destinations
18
- end
19
-
20
- it 'renames the sources to the destinations' do
21
- expect(File)
22
- .to receive(:rename)
23
- .with sources.first, destinations.first
24
- renamer.execute!
25
- end
26
- end
27
-
28
- context 'when destinations are the same as sources' do
29
- let(:destinations) { sources }
30
-
31
- it 'renames nothing' do
32
- expect(File).not_to receive :rename
33
- renamer.execute!
34
- end
35
- end
36
- end
37
- end
@@ -1,5 +0,0 @@
1
- require 'mmve'
2
-
3
- require 'support/exit_helpers'
4
-
5
- ENV['EDITOR'] = 'true'
@@ -1,6 +0,0 @@
1
- module ExitHelpers
2
- def trap_exit
3
- yield
4
- rescue SystemExit
5
- end
6
- end