tweezer 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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