vendorificator 0.0.1

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.
Files changed (57) hide show
  1. data/.gitignore +19 -0
  2. data/.travis.yml +9 -0
  3. data/Gemfile +11 -0
  4. data/LICENSE +22 -0
  5. data/README.md +45 -0
  6. data/Rakefile +29 -0
  7. data/bin/vendor +4 -0
  8. data/bin/vendorify +6 -0
  9. data/examples/Vendorfile +25 -0
  10. data/features/chef_cookbook.feature +44 -0
  11. data/features/deprecated.feature +17 -0
  12. data/features/fixtures/git/testrepo/HEAD +1 -0
  13. data/features/fixtures/git/testrepo/config +7 -0
  14. data/features/fixtures/git/testrepo/description +1 -0
  15. data/features/fixtures/git/testrepo/hooks/applypatch-msg.sample +15 -0
  16. data/features/fixtures/git/testrepo/hooks/commit-msg.sample +24 -0
  17. data/features/fixtures/git/testrepo/hooks/post-update.sample +8 -0
  18. data/features/fixtures/git/testrepo/hooks/pre-applypatch.sample +14 -0
  19. data/features/fixtures/git/testrepo/hooks/pre-commit.sample +50 -0
  20. data/features/fixtures/git/testrepo/hooks/pre-rebase.sample +169 -0
  21. data/features/fixtures/git/testrepo/hooks/prepare-commit-msg.sample +36 -0
  22. data/features/fixtures/git/testrepo/hooks/update.sample +128 -0
  23. data/features/fixtures/git/testrepo/info/exclude +6 -0
  24. data/features/fixtures/git/testrepo/info/refs +5 -0
  25. data/features/fixtures/git/testrepo/objects/info/packs +2 -0
  26. data/features/fixtures/git/testrepo/objects/pack/pack-46f7621b6a6b9b1c22dd15c08d457dfedf76e55f.idx +0 -0
  27. data/features/fixtures/git/testrepo/objects/pack/pack-46f7621b6a6b9b1c22dd15c08d457dfedf76e55f.pack +0 -0
  28. data/features/fixtures/git/testrepo/packed-refs +6 -0
  29. data/features/fixtures/git/testrepo/refs/heads/.sentinel +0 -0
  30. data/features/fixtures/git/testrepo/refs/tags/.sentinel +0 -0
  31. data/features/fixtures/vcr_cassettes/vendorificator.yml +2375 -0
  32. data/features/git.feature +12 -0
  33. data/features/needed.feature +16 -0
  34. data/features/smoke.feature +14 -0
  35. data/features/status.feature +47 -0
  36. data/features/step_definitions/basic.rb +52 -0
  37. data/features/step_definitions/git.rb +39 -0
  38. data/features/step_definitions/vendorificator.rb +27 -0
  39. data/features/support/env.rb +32 -0
  40. data/features/support/transform_pattern.rb +12 -0
  41. data/features/support/world_git.rb +40 -0
  42. data/features/support/world_runs.rb +90 -0
  43. data/features/tarball.feature +63 -0
  44. data/features/tarball_edit.feature +15 -0
  45. data/features/vendor.feature +16 -0
  46. data/lib/vendorificator/cli.rb +233 -0
  47. data/lib/vendorificator/config.rb +72 -0
  48. data/lib/vendorificator/hooks/chef_cookbook.rb +23 -0
  49. data/lib/vendorificator/repo.rb +69 -0
  50. data/lib/vendorificator/vendor/archive.rb +90 -0
  51. data/lib/vendorificator/vendor/chef_cookbook.rb +58 -0
  52. data/lib/vendorificator/vendor/git.rb +47 -0
  53. data/lib/vendorificator/vendor.rb +260 -0
  54. data/lib/vendorificator/version.rb +3 -0
  55. data/lib/vendorificator.rb +9 -0
  56. data/vendorificator.gemspec +30 -0
  57. metadata +321 -0
@@ -0,0 +1,233 @@
1
+ require 'thor'
2
+
3
+ require 'vendorificator'
4
+
5
+ module Vendorificator
6
+ class CLI < Thor
7
+ include Vendorificator
8
+
9
+ check_unknown_options! :except => [:git, :diff, :log]
10
+ stop_on_unknown_option! :git, :diff, :log
11
+
12
+ default_task :sync
13
+
14
+ class_option :file, :aliases => '-f', :type => :string, :banner => 'PATH'
15
+ class_option :debug, :aliases => '-d', :type => :boolean, :default => false
16
+ class_option :quiet, :aliases => ['-q'], :default => false, :type => :boolean
17
+ class_option :modules, :type => :string, :default => '',
18
+ :banner => 'mod1,mod2,...,modN',
19
+ :desc => 'Run only for specified modules (name or path, comma separated)'
20
+
21
+ def initialize(*args)
22
+ super
23
+ Grit.debug = true if options[:debug]
24
+ Vendorificator::Config.from_file(find_vendorfile)
25
+ Vendorificator::Config[:shell] = shell
26
+
27
+ class << shell
28
+ # Make say_status always say it.
29
+ def quiet?
30
+ false
31
+ end
32
+ end
33
+ end
34
+
35
+ desc :sync, "Download new or updated vendor files"
36
+ def sync
37
+ ensure_clean_repo!
38
+ Vendorificator::Config.each_module(*modules) do |mod|
39
+ say_status :module, mod.name
40
+ begin
41
+ shell.padding += 1
42
+ mod.run!
43
+ ensure
44
+ shell.padding -= 1
45
+ end
46
+ end
47
+ end
48
+
49
+ desc "status", "List known vendor modules and their status"
50
+ def status
51
+ say_status 'WARNING', 'Git repository is not clean', :red unless repo.clean?
52
+ Vendorificator::Config.each_module(*modules) do |mod|
53
+ status_line = mod.to_s
54
+
55
+ updatable = mod.updatable?
56
+ if updatable
57
+ if updatable == true
58
+ status_line << ' (updatable)'
59
+ else
60
+ status_line << " (updatable to #{updatable.name})"
61
+ end
62
+ end
63
+
64
+ say_status( mod.status.to_s.gsub('_', ' '), status_line,
65
+ ( mod.status==:up_to_date ? :green : :yellow ) )
66
+ end
67
+ end
68
+
69
+ desc :pull, "Pull upstream branches from a remote repository"
70
+ method_option :remote, :aliases => ['-r'], :default => nil
71
+ method_option :dry_run, :aliases => ['-n'], :default => false, :type => :boolean
72
+ def pull
73
+ ensure_clean_repo!
74
+ remotes = options[:remote] ? options[:remote].split(',') : conf[:remotes]
75
+ remotes.each do |remote|
76
+ indent 'remote', remote do
77
+ repo.pull(remote, options)
78
+ end
79
+ end
80
+ end
81
+ desc "git GIT_COMMAND [GIT_ARGS [...]]",
82
+ "Run a git command for specified modules"
83
+ long_desc <<EOF
84
+ Run a git command for specified modules. Within GIT_ARGS arguments,
85
+ you can use @MERGED@ and @PATH@ tags, which will be substituted with
86
+ mo#dule's most recently merged revision and full path of its work
87
+ directory.
88
+
89
+ The 'diff' and 'log' commands are simple aliases for 'git' command.
90
+
91
+ Examples:
92
+ vendor git log @MERGED@..HEAD -- @PATH@ # basic 'vendor log'
93
+ vendor git diff --stat @MERGED@ -- @PATH@ # 'vendor diff', as diffstat
94
+ EOF
95
+ method_option :only_changed, :default => false, :type => :boolean
96
+ def git(command, *args)
97
+ Vendorificator::Config.each_module(*modules) do |mod|
98
+ unless mod.merged
99
+ say_status 'unmerged', mod.to_s, :red unless options[:only_changed]
100
+ next
101
+ end
102
+
103
+ actual_args = args.dup.map do |arg|
104
+ arg.
105
+ gsub('@MERGED@', mod.merged).
106
+ gsub('@PATH@', mod.work_dir)
107
+ end
108
+
109
+ output = repo.git.native(command, {}, *actual_args)
110
+ if output.empty?
111
+ say_status 'unchanged', mod.to_s, :green unless options[:only_changed]
112
+ else
113
+ say_status 'changed', mod.to_s, :yellow
114
+ end
115
+ puts output unless options[:quiet] || output.empty?
116
+ end
117
+ end
118
+
119
+ desc "diff [OPTIONS] [GIT OPTIONS]",
120
+ "Show differences between work tree and upstream module(s)"
121
+ method_option :only_changed, :default => false, :type => :boolean
122
+ def diff(*args)
123
+ invoke :git, %w'diff' + args + %w'@MERGED@ -- @PATH@'
124
+ end
125
+
126
+ desc "log [OPTIONS] [GIT OPTIONS]",
127
+ "Show git log of commits added to upstream module(s)"
128
+ method_option :only_changed, :default => false, :type => :boolean
129
+ def log(*args)
130
+ invoke :git, %w'log' + args + %w'@MERGED@..HEAD -- @PATH@'
131
+ end
132
+
133
+ desc :pry, 'Pry into the binding', :hide => true
134
+ def pry
135
+ require 'pry'
136
+ binding.pry
137
+ end
138
+
139
+ def self.start
140
+ # Make --git-options always quoted
141
+ if i = ARGV.index('--git-options')
142
+ ARGV[i+1,0] = '--'
143
+ end
144
+
145
+ if ENV['FIXTURES_DIR']
146
+ require 'vcr'
147
+ VCR.configure do |c|
148
+ c.cassette_library_dir = File.join(ENV['FIXTURES_DIR'], 'vcr_cassettes')
149
+ c.default_cassette_options = { :record => :new_episodes }
150
+ c.hook_into :fakeweb
151
+ end
152
+ VCR.use_cassette(ENV['VCR_CASSETTE'] || 'vendorificator') do
153
+ super
154
+ end
155
+ else
156
+ super
157
+ end
158
+ end
159
+
160
+ private
161
+
162
+ def split_git_options(args)
163
+ case i = args.index('--git-options')
164
+ when nil then [ args, [] ]
165
+ when 0 then [ [], args[1..-1] ]
166
+ else [ args[0..(i-1)], args[(i+1)..-1] ]
167
+ end
168
+ end
169
+
170
+ def modules
171
+ options[:modules].split(',').map(&:strip)
172
+ end
173
+
174
+ def conf
175
+ Vendorificator::Config
176
+ end
177
+
178
+ def repo
179
+ Vendorificator::Config.repo
180
+ end
181
+
182
+ def fail!(message, exception_message='I give up.')
183
+ say_status('FATAL', message, :red)
184
+ raise Thor::Error, 'I give up.'
185
+ end
186
+
187
+ def indent(*args, &block)
188
+ say_status *args unless args.empty?
189
+ shell.padding += 1
190
+ yield
191
+ ensure
192
+ shell.padding -= 1
193
+ end
194
+
195
+ # Find proper Vendorfile
196
+ def find_vendorfile
197
+ given = options.file || ENV['VENDORFILE']
198
+ return Pathname.new(given).expand_path if given && !given.empty?
199
+
200
+ Pathname.pwd.ascend do |dir|
201
+ vf = dir.join('Vendorfile')
202
+ return vf if vf.exist?
203
+
204
+ vf = dir.join('config/vendor.rb')
205
+ return vf if vf.exist?
206
+
207
+ # avoid stepping above the tmp directory when testing
208
+ if ENV['VENDORIFICATOR_SPEC_RUN'] &&
209
+ dir.join('vendorificator.gemspec').exist?
210
+ raise RuntimeError, "Vendorfile not found"
211
+ end
212
+ end
213
+
214
+ raise RuntimeError, "Vendorfile not found"
215
+ end
216
+
217
+ def ensure_clean_repo!
218
+ unless repo.clean?
219
+ fail!('Repository is not clean.')
220
+ end
221
+ end
222
+ end
223
+ end
224
+
225
+ # Monkey patch over https://github.com/wycats/thor/pull/298
226
+ class Thor::Options
227
+ alias_method :_orig_current_is_switch?, :current_is_switch?
228
+ def current_is_switch?
229
+ rv = _orig_current_is_switch?
230
+ @parsing_options = false if !rv[0] && @stop_on_unknown && @parsing_options
231
+ rv
232
+ end
233
+ end
@@ -0,0 +1,72 @@
1
+ require 'pathname'
2
+
3
+ require 'mixlib/config'
4
+
5
+ require 'vendorificator/repo'
6
+
7
+ module Vendorificator
8
+ class Config
9
+ extend Mixlib::Config
10
+
11
+ configure do |c|
12
+ c[:root] = Pathname.getwd
13
+ c[:basedir] = 'vendor'
14
+ c[:branch_prefix] = 'vendor'
15
+ c[:modules] = []
16
+ c[:remotes] = %w(origin)
17
+ end
18
+
19
+ def self.from_file(filename)
20
+ pathname = Pathname.new(filename).cleanpath.expand_path
21
+ self[:root_dir] =
22
+ if ( pathname.basename.to_s == 'vendor.rb' &&
23
+ pathname.dirname.basename.to_s == 'config' )
24
+ # Correctly recognize root dir if main config is 'config/vendor.rb'
25
+ pathname.dirname.dirname
26
+ else
27
+ pathname.dirname
28
+ end
29
+ self[:vendorfile_path] = pathname
30
+ self[:lockfile_path] = pathname.dirname.join(pathname.basename.to_s + '.lock')
31
+ super(pathname.to_s)
32
+ end
33
+
34
+ def self.repo
35
+ @repo ||= begin
36
+ git_root_path = self[:repo_dir] || _find_git_root
37
+ raise "Can't find Git repository" unless git_root_path
38
+ Vendorificator::Repo.new( git_root_path.to_s )
39
+ end
40
+ end
41
+
42
+ def self.each_module(*modules)
43
+ module_paths = modules.map { |m| File.expand_path(m) }
44
+
45
+ # We don't use self[:modules].each here, because mod.run! is
46
+ # explicitly allowed to append to Config[:modules], and #each
47
+ # fails to catch up on some Ruby implementations.
48
+ i = 0
49
+ while true
50
+ break if i >= Vendorificator::Config[:modules].length
51
+ mod = Vendorificator::Config[:modules][i]
52
+ yield mod if
53
+ modules.empty? ||
54
+ modules.include?(mod.name) ||
55
+ module_paths.include?(mod.work_dir)
56
+ i += 1
57
+
58
+ # Add dependencies
59
+ work_dirs = Vendorificator::Config[:modules].map(&:work_dir)
60
+ Vendorificator::Config[:modules] +=
61
+ mod.dependencies.reject { |dep| work_dirs.include?(dep.work_dir) }
62
+ end
63
+ end
64
+
65
+ def self._find_git_root
66
+ self[:root_dir].ascend do |dir|
67
+ return dir if dir.join('.git').exist?
68
+ end
69
+ end
70
+ private_class_method :_find_git_root
71
+ end
72
+ end
@@ -0,0 +1,23 @@
1
+ require 'chef/cookbook/metadata'
2
+
3
+ module Vendorificator::Hooks
4
+ module ChefCookbookDependencies
5
+ # Add required Chef cookbooks to vendor modules
6
+ def dependencies
7
+ ignored = Vendorificator::Config[:chef_cookbook_ignore_dependencies] || []
8
+ metadata = File.join(self.work_dir, 'metadata.rb')
9
+
10
+ unless File.exist?(metadata)
11
+ shell.say_status 'WARNING', "Metadata of #{name} does not exist at #{metadata}, could not gather dependencies", :red
12
+ return super
13
+ end
14
+
15
+ cbmd = Chef::Cookbook::Metadata.new
16
+ cbmd.from_file(metadata)
17
+
18
+ super + cbmd.dependencies.
19
+ reject { |name, version| ignored.include?(name) }.
20
+ map { |name, version| Vendorificator::Vendor::ChefCookbook.new(name) }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,69 @@
1
+ require 'grit'
2
+
3
+ module Vendorificator
4
+ class Repo < Grit::Repo
5
+ # True if repository doesn't contain uncommitted changes.
6
+ def clean?
7
+ # copy code from http://stackoverflow.com/a/3879077/16390
8
+ git.native :update_index, {}, '-q', '--ignore-submodules', '--refresh'
9
+ git.native :diff_files, {:raise => true}, '--quiet', '--ignore-submodules', '--'
10
+ git.native :diff_index, {:raise => true}, '--cached', '--quiet', 'HEAD', '--ignore-submodules', '--'
11
+ true
12
+ rescue Grit::Git::CommandFailed
13
+ false
14
+ end
15
+
16
+ # Update vendor branches & tags from an upstream repository
17
+ def pull(remote, options={})
18
+ raise RuntimeError, "Unknown remote #{remote}" unless remote_list.include?(remote)
19
+
20
+ git.fetch({}, remote)
21
+ git.fetch({:tags => true}, remote)
22
+
23
+ ref_rx = /^#{Regexp.quote(remote)}\//
24
+ remote_branches = Hash[remotes.map{|r| [$',r] if r.name =~ ref_rx }.compact]
25
+
26
+ # FIXME: should we depend on Vendorificator::Config here?
27
+ Vendorificator::Config.each_module do |mod|
28
+ remote_head = remote_branches[mod.branch_name]
29
+ ours = mod.head && mod.head.commit.sha
30
+ theirs = remote_head && remote_head.commit.sha
31
+
32
+ if remote_head
33
+ if not mod.head
34
+ say_status 'new', mod.branch_name, :yellow
35
+ git.branch({:track=>true}, mod.branch_name, remote_head.name) unless options[:dry_run]
36
+ elsif ours == theirs
37
+ say_status 'unchanged', mod.branch_name
38
+ elsif fast_forwardable?(theirs, ours)
39
+ say_status 'updated', mod.name, :yellow
40
+ unless options[:dry_run]
41
+ mod.in_branch do
42
+ git.merge({:ff_only => true}, remote_head.name)
43
+ end
44
+ end
45
+ elsif fast_forwardable?(ours, theirs)
46
+ say_status 'older', mod.branch_name
47
+ else
48
+ say_status 'complicated', mod.branch_name, :red
49
+ indent do
50
+ say 'Merge it yourself.'
51
+ end
52
+ end
53
+ else
54
+ say_status 'unknown', mod.branch_name
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def conf
61
+ Vendorificator::Config
62
+ end
63
+
64
+ def say_status(*args)
65
+ conf[:shell].say_status(*args) if conf[:shell]
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,90 @@
1
+ require 'digest'
2
+ require 'open-uri'
3
+ require 'tempfile'
4
+ require 'uri'
5
+
6
+ require 'escape'
7
+
8
+ require 'vendorificator/vendor'
9
+
10
+ class Vendorificator::Vendor::Archive < Vendorificator::Vendor
11
+ arg_reader :url, :strip_root, :type, :checksum, :filename, :basename, :extname, :unpack
12
+ attr_reader :conjured_checksum
13
+
14
+ def initialize(name, args={}, &block)
15
+ no_url_given = !args[:url]
16
+
17
+ args[:url] ||= name
18
+ args[:filename] ||= URI::parse(args[:url]).path.split('/').last
19
+
20
+ case args[:filename]
21
+ when /\.(tar\.|t)gz$/
22
+ args[:type] ||= :targz
23
+ args[:unpack] ||= 'tar -xzf'
24
+ when /\.tar\.bz2$/
25
+ args[:type] ||= :tarbz2
26
+ args[:unpack] ||= 'tar -xjf'
27
+ when /\.zip$/
28
+ args[:type] ||= :zip
29
+ args[:unpack] ||= 'unzip'
30
+ when /\.[^\.][^\.]?[^\.]?[^\.]?$/
31
+ args[:type] ||=
32
+ begin
33
+ unless args[:unpack]
34
+ raise RuntimeError,
35
+ "Unknown file type #{$&.inspect}, please provide :unpack argument"
36
+ end
37
+ $&
38
+ end
39
+ else
40
+ args[:basename] ||= args[:filename]
41
+ args[:extname] ||= ''
42
+ unless args[:unpack] || [:targz, :tarbz2, :zip].include?(args[:type])
43
+ raise RuntimeError, "Unknown file type for #{args[:filename].inspect}, please provide :unpack or :type argument"
44
+ end
45
+ end
46
+ args[:basename] ||= $`
47
+ args[:extname] ||= $&
48
+
49
+ name = args[:basename] if no_url_given
50
+
51
+ super(name, args, &block)
52
+ end
53
+
54
+ def conjure!
55
+ shell.say_status :download, url
56
+ archive = Tempfile.new([basename, extname])
57
+ archive.write( open(url).read )
58
+ archive.close
59
+ @conjured_checksum = Digest::SHA256.file(archive.path).hexdigest
60
+ raise RuntimeError, "Checksum error" if checksum && checksum!=conjured_checksum
61
+ shell.say_status :unpack, filename
62
+ system "#{unpack} #{Escape.shell_single_word archive.path}"
63
+ if Dir.entries('.').length == 3 && !args[:no_strip_root]
64
+ root = (Dir.entries('.') - %w(.. .)).first
65
+ root_entries = Dir.entries(root) - %w(.. .)
66
+ while root_entries.include?(root)
67
+ FileUtils::mv root, root+"~"
68
+ root << "~"
69
+ end
70
+ FileUtils::mv root_entries.map { |e| File.join(root, e) }, '.'
71
+ FileUtils::rmdir root
72
+ end
73
+ super
74
+ ensure
75
+ archive.close
76
+ archive.unlink
77
+ end
78
+
79
+ def upstream_version
80
+ filename
81
+ end
82
+
83
+ def conjure_commit_message
84
+ rv = "Conjured archive #{name} from #{filename}\nOrigin: #{url}\nChecksum: #{conjured_checksum}\n"
85
+ rv << "Version: #{version}\n" if version
86
+ rv
87
+ end
88
+
89
+ install!
90
+ end
@@ -0,0 +1,58 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'json'
4
+
5
+ require 'vendorificator/vendor/archive'
6
+ require 'vendorificator/hooks/chef_cookbook'
7
+
8
+ class Vendorificator::Vendor::ChefCookbook < Vendorificator::Vendor::Archive
9
+ include Vendorificator::Hooks::ChefCookbookDependencies
10
+
11
+ @method_name = :chef_cookbook
12
+ @category = :cookbooks
13
+
14
+ API_PREFIX = 'http://cookbooks.opscode.com/api/v1/cookbooks/'
15
+
16
+ def initialize(name, args={}, &block)
17
+ args[:url] ||= true # to avoid having name treated as url
18
+ args[:filename] ||= "#{name}.tgz"
19
+
20
+ super(name, args, &block)
21
+ end
22
+
23
+ def api_data(v=nil)
24
+ v = v.gsub(/[^0-9]/, '_') if v
25
+ @api_data ||= {}
26
+ @api_data[v] ||=
27
+ begin
28
+ url = "#{API_PREFIX}#{name}"
29
+ url << "/versions/#{v}" if v
30
+ JSON::load(Net::HTTP.get_response(URI.parse(url)).body)
31
+ end
32
+ end
33
+
34
+ def cookbook_data
35
+ @cookbook_data ||= api_data(version)
36
+ end
37
+
38
+ def upstream_version
39
+ URI::parse(api_data['latest_version']).path.split('/').last.gsub('_', '.')
40
+ end
41
+
42
+ def url
43
+ cookbook_data['file']
44
+ end
45
+
46
+ def conjure!
47
+ super
48
+ # Some Opscode Community tarballs include a confusing .git file,
49
+ # we don't want this.
50
+ FileUtils::rm_f '.git'
51
+ end
52
+
53
+ def conjure_commit_message
54
+ "Conjured cookbook #{name} version #{version}\nOrigin: #{url}\nChecksum: #{conjured_checksum}\n"
55
+ end
56
+
57
+ install!
58
+ end
@@ -0,0 +1,47 @@
1
+ require 'fileutils'
2
+
3
+ require 'grit'
4
+
5
+ require 'vendorificator/vendor'
6
+
7
+ class Vendorificator::Vendor::Git < Vendorificator::Vendor
8
+ arg_reader :repository, :revision, :branch
9
+ attr_reader :module_repo, :conjured_revision
10
+
11
+ def initialize(name, args={}, &block)
12
+ unless args.include?(:repository)
13
+ args[:repository] = name
14
+ name = name.split('/').last.sub(/\.git$/, '')
15
+ end
16
+ super(name, args, &block)
17
+ end
18
+
19
+ def conjure!
20
+ shell.say_status :clone, repository
21
+ Grit::Git.new('.').clone({}, repository, '.')
22
+ @module_repo = Grit::Repo.new('.')
23
+
24
+ if revision
25
+ module_repo.git.checkout({:b => 'vendorified'}, revision)
26
+ elsif branch
27
+ module_repo.git.checkout({:b => 'vendorified'}, "origin/#{branch}")
28
+ end
29
+
30
+ super
31
+ @conjured_revision = module_repo.head.commit.id
32
+ FileUtils::rm_rf '.git'
33
+ end
34
+
35
+ def upstream_version
36
+ conjured_revision
37
+ end
38
+
39
+ def conjure_commit_message
40
+ rv = "Conjured git module #{name} "
41
+ rv << "version #{version} " if version
42
+ rv << "revision #{conjured_revision}"
43
+ rv
44
+ end
45
+
46
+ install!
47
+ end