tweezer 0.1.3 → 0.2.0

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,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YTY3YmM0ZTA2YjQ1MDc3ZWY5MzI1OGIwZGU3ZjBlZTIzODA1YzkyZg==
4
+ MmJhZTNjOWE5MWE4MWM2Njc2MTg2YzdmZDg4YjA4MjJhMDRkYmYyMQ==
5
5
  data.tar.gz: !binary |-
6
- NTA4YWU1MTBiMjEwOTE5Nzk0NDIwNjgwNzY2MTdjMTY3YjQxOTFjMQ==
6
+ YzYzMDM5OTk4MjcwODhiMTFmM2I5MjhhNzk3ZWM5MjFiMzlkNjYyNQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZDE5ZGZmNTJkNzA0NGU1NWI4ZWNhMDMxMmY1MTkyZjM3MzQzNjE2ZGY1YzY0
10
- NDY2MDZlYmM1NmYwMzBkMzVkYTEzMjc5ZDM3OGIxY2IzZjg3NDI3MmE3OWQy
11
- Y2U3NmMyOGQ3NTUzODA5NjkwZmY5MDgzM2I4NzdlMzZiZDkyNzc=
9
+ M2NkZTJhZjE2N2Y5MmIxN2FmMmQxYzAzYzMzNGE5ODc4NmNlZTIwYTU3Mzhm
10
+ MDcyNzIwZjJkMmUxODI4MmIzMjAxMmVlNTdjYzVhMTM5ZDUzODZjYmYxZTg3
11
+ MGIxZmZjYzdkNWMzYWQyNmQ5YWNkNjJjYzhiMTEzMmJkOTg4NmY=
12
12
  data.tar.gz: !binary |-
13
- MWQ0MmI2NzU2YTkzZWIwMTg5YzdkZDYwMDIzZjE1ZmFlOTc3NGU3ZmYzY2Jk
14
- NDIwNTIyNWNkODEwMzExYmRiMzE5NWVjODYwZDk2ZjZhM2E2ZjM5ODAzNmMz
15
- N2VmNjRiMWQ1MTUyMGFkZjg5NjU2ZmU2MmExMjdlYmY1MmVhNzQ=
13
+ NTI4MTFiYzJkY2U0ZjI3MDA1NzMyOTljYzRmNzU4MmMzZTVlN2NhZTA1NGVl
14
+ YjY5NzAwZGVjY2UwNzljZDRkOTM0NjlmYmM1OWNlM2MwMThiMGNhMjcxYmIx
15
+ MTljYWRiYzE5NTUyM2FjM2QxOWRjNGQ4Yjg4YjY2NzBlOGVjYTc=
@@ -1,2 +1,5 @@
1
1
  Style/Documentation:
2
2
  Enabled: false
3
+
4
+ Metrics/ClassLength:
5
+ Enabled: false
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Tweezer [![Build Status](https://travis-ci.org/glittershark/tweezer.svg?branch=master)](https://travis-ci.org/glittershark/tweezer)
2
2
 
3
- **Tweezer** is a CLI tool for editing your Gemfile.
3
+ **Tweezer** is a CLI tool for editing your Gemfile that goes to great extents to
4
+ ensure the Gemfile remains both valid and idiomatic
4
5
 
5
6
  Tweezer is currently usable, but should be considered a WIP in that it's
6
7
  reasonably untested and might muck up your Gemfile in any number of nasty ways
@@ -16,6 +17,9 @@ gem install tweezer
16
17
 
17
18
  ## Usage
18
19
 
20
+ For full documentation, run `tweezer help` and `tweezer help COMMAND`.
21
+
22
+ ### Adding new gems - `tweezer add`
19
23
  ```sh
20
24
  tweezer add rake # Adds rake to the end of the default group in your Gemfile
21
25
 
@@ -27,7 +31,14 @@ tweezer add rspec --group test # Adds rspec to the 'test' group in your gemfile.
27
31
  # the most idiomatic possible Gemfile
28
32
  ```
29
33
 
30
- For further documentation, run `tweezer help` and `tweezer help COMMAND`.
34
+ ### Changing attributes of existing gems - `tweezer alter`
35
+ ```sh
36
+ tweezer alter rake -v '~> 10.4.2' # Changes rake in the gemfile to be pinned to
37
+ # 10.4.2
38
+
39
+ tweezer alter rake -p '~/code/rake' # Changes rake in the gemfile to be
40
+ # installed from `~/code/rake`
41
+ ```
31
42
 
32
43
  ## Why?
33
44
 
@@ -36,6 +36,7 @@ module Tweezer
36
36
  end
37
37
 
38
38
  def unparse_hash_node(node)
39
+ return {} unless node
39
40
  fail ArgumentError unless node.type == :hash
40
41
  Hash[node.children.map do |child|
41
42
  [child.children[0].children[0], child.children[1]]
@@ -17,11 +17,35 @@ module Tweezer
17
17
  desc 'add GEM [VERSION]',
18
18
  'add GEM to the gemfile, optionally pinned to VERSION'
19
19
  option :groups, type: :array, aliases: '-g',
20
- desc: 'Groups to add the gem to'
21
- def add(name, version = nil)
22
- groups = options[:groups].map(&:to_sym) if options[:groups]
23
- @gemfile.add_gem(name, version, groups: groups || [])
20
+ desc: 'groups to add the gem to'
21
+ option :path, aliases: '-p',
22
+ desc: 'path on the system to install the gem from'
23
+ def add(name)
24
+ @gemfile.add_gem(name, **gem_opts)
24
25
  @gemfile.save!
25
26
  end
27
+
28
+ desc 'alter GEM',
29
+ 'alter GEM that is already in the gemfile, with the given options'
30
+ option :version, aliases: '-v', desc: 'version to pin the gem to'
31
+ option :groups, aliases: '-g',
32
+ type: :array,
33
+ desc: 'groups to add the gem to'
34
+ option :path, aliases: '-p',
35
+ desc: 'path on the system to install the gem from'
36
+ def alter(name)
37
+ @gemfile.alter_gem(name, **gem_opts)
38
+ @gemfile.save!
39
+ end
40
+
41
+ private
42
+
43
+ def gem_opts
44
+ @gem_opts ||= {
45
+ groups: options[:groups] ? options[:groups].map(&:to_sym) : [],
46
+ version: options[:version] || '',
47
+ path: options[:path]
48
+ }
49
+ end
26
50
  end
27
51
  end
@@ -1,3 +1,4 @@
1
1
  module Tweezer
2
2
  GemAlreadyPresent = Class.new(RuntimeError)
3
+ GemNotPresent = Class.new(RuntimeError)
3
4
  end
@@ -2,26 +2,26 @@ module Tweezer
2
2
  class Gem
3
3
  include Tweezer::ASTHelper
4
4
 
5
- def initialize(node_or_name, version = nil, opts = {})
5
+ def initialize(node_or_name, opts = {})
6
6
  return init_from_node(node_or_name) if node_or_name.is_a?(
7
7
  Parser::AST::Node)
8
8
 
9
9
  @name = node_or_name
10
+ alter!(opts)
11
+ end
10
12
 
11
- if version.is_a? Hash
12
- @version = nil
13
- opts = version
14
- else
15
- @version = version
16
- end
17
-
13
+ def alter!(opts)
14
+ @version = opts[:version]
18
15
  @groups = opts[:groups]
16
+ @path = opts[:path]
17
+ @opts = opts
19
18
  end
20
19
 
21
20
  def to_node
22
21
  args = [nil, :gem, s(:str, name)]
23
22
  args << s(:str, version) if version
24
- args << s(:hash, groups_to_node) unless groups.empty?
23
+ opts_node = opts_to_node
24
+ args << opts_node if opts_node
25
25
 
26
26
  Parser::AST::Node.new(:send, args)
27
27
  end
@@ -35,7 +35,8 @@ module Tweezer
35
35
  node.children[1] == :gem
36
36
  end
37
37
 
38
- attr_reader :name, :version
38
+ attr_reader :name
39
+ attr_accessor :version, :path
39
40
  attr_writer :groups
40
41
 
41
42
  def groups
@@ -53,8 +54,9 @@ module Tweezer
53
54
  @name = arguments[0].children[0]
54
55
  @version = arguments[1].children[0] if arguments[1]
55
56
 
56
- return unless opts
57
- @groups = groups_from_node(unparse_hash_node(opts)[:group])
57
+ opts_h = unparse_hash_node(opts)
58
+ @groups = groups_from_node(opts_h[:group])
59
+ @path = path_from_node(opts_h[:path])
58
60
  end
59
61
  # rubocop:enable Metrics/AbcSize
60
62
 
@@ -68,7 +70,16 @@ module Tweezer
68
70
  end)
69
71
  end
70
72
 
73
+ def opts_to_node
74
+ pairs = []
75
+ pairs << groups_to_node unless groups.empty?
76
+ pairs << s(:pair, s(:sym, :path), s(:str, path)) if path
77
+ return if pairs.empty?
78
+ s(:hash, *pairs)
79
+ end
80
+
71
81
  def groups_from_node(node)
82
+ return [] unless node
72
83
  case node.type
73
84
  when :sym then [node.children[0]]
74
85
  when :array then node.children.flat_map(&:children)
@@ -76,6 +87,12 @@ module Tweezer
76
87
  end
77
88
  end
78
89
 
90
+ def path_from_node(node)
91
+ return unless node
92
+ fail ArgumentError unless node.type == :str
93
+ node.children.first
94
+ end
95
+
79
96
  def check_node!(node)
80
97
  return if self.class.gem_node?(node)
81
98
  fail ArgumentError, "Not a call to `gem`: #{node.inspect}"
@@ -55,6 +55,13 @@ module Tweezer
55
55
  # rubocop:enable Metrics/MethodLength
56
56
  # rubocop:enable Metrics/AbcSize
57
57
 
58
+ def alter_gem(name, **options)
59
+ gem = gems.find { |g| g.name == name } || fail(GemNotPresent)
60
+ old_node = gem.to_node
61
+ gem.alter!(options)
62
+ replace_gem!(old_node, gem.to_node)
63
+ end
64
+
58
65
  def dump
59
66
  dumped = Unparser.unparse(ast, comments).dup
60
67
  dumped << "\n" unless dumped[-1] == "\n"
@@ -113,6 +120,11 @@ module Tweezer
113
120
  @ast = @ast.updated(nil, nodes)
114
121
  end
115
122
 
123
+ def replace_gem!(old_node, new_node)
124
+ nodes = ast.children.map { |node| node == old_node ? new_node : node }
125
+ @ast = @ast.updated(nil, nodes)
126
+ end
127
+
116
128
  def gem_to_group_block!(gem)
117
129
  nodes = ast.children.flat_map do |node|
118
130
  next [node] unless node == gem.to_node
@@ -1,3 +1,3 @@
1
1
  module Tweezer
2
- VERSION = '0.1.3'
2
+ VERSION = '0.2.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tweezer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Griffin Smith
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-10-20 00:00:00.000000000 Z
11
+ date: 2016-01-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser