obazoud-git-external 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/git-external +196 -0
- metadata +68 -0
data/bin/git-external
ADDED
@@ -0,0 +1,196 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
$root_dir = `git rev-parse --show-toplevel`.chomp
|
5
|
+
$externals_file = "#{$root_dir}/.gitexternals"
|
6
|
+
$ignore_file = "#{$root_dir}/.gitignore"
|
7
|
+
$configurations = {}
|
8
|
+
|
9
|
+
def usage
|
10
|
+
puts "Usage: git external add <repository-url> <path> [<branch>]"
|
11
|
+
puts " or: git external status"
|
12
|
+
puts " or: git external init [--] [<path>...]"
|
13
|
+
puts " or: git external update [--] [<path>...]"
|
14
|
+
puts " or: git external cmd '<command>'"
|
15
|
+
puts " or: git external list"
|
16
|
+
end
|
17
|
+
|
18
|
+
def load_configuration
|
19
|
+
if File.file? $externals_file
|
20
|
+
lines = `git config -l -f #{$externals_file}`.split(/\n/)
|
21
|
+
$configurations = {}
|
22
|
+
lines.each do |line|
|
23
|
+
if line =~ /^external\.([^$]+)\.([^=]+)=(.*)$/
|
24
|
+
$configurations[$1.chomp] ||= {}
|
25
|
+
$configurations[$1.chomp][$2.chomp] = $3.chomp
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def print_configuration
|
32
|
+
$configurations.each do |name, config|
|
33
|
+
puts name
|
34
|
+
config.each do |key, value|
|
35
|
+
puts "\t#{key}: #{value}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def normalize_url(url)
|
41
|
+
if url =~ /^\./
|
42
|
+
origin_url = `git config --get remote.origin.url`.chomp
|
43
|
+
|
44
|
+
unless origin_url =~ /^\w+:\/\//
|
45
|
+
if origin_url =~ /^([^:\/]+):([^:]+)/
|
46
|
+
origin_url = "ssh://#{$1}/#{$2}"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
require 'uri'
|
51
|
+
uri = URI.parse URI.encode origin_url
|
52
|
+
uri.path = File.expand_path(url, uri.path)
|
53
|
+
uri.to_s
|
54
|
+
else
|
55
|
+
url
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Check if a branch exists
|
60
|
+
def branch_exists(path, branch)
|
61
|
+
branches = `cd #{path}; git branch`
|
62
|
+
regex = Regexp.new('[\\n\\s\\*]+' + Regexp.escape(branch.to_s) + '\\n')
|
63
|
+
result = ((branches =~ regex) ? true : false)
|
64
|
+
return result
|
65
|
+
end
|
66
|
+
|
67
|
+
def init_external(url, path, branch='master')
|
68
|
+
require 'fileutils'
|
69
|
+
if File.directory? "#{path}/.git"
|
70
|
+
puts "- Repository already exists"
|
71
|
+
else
|
72
|
+
FileUtils.makedirs File.dirname(path)
|
73
|
+
url = normalize_url url
|
74
|
+
system "git clone #{url} #{path}"
|
75
|
+
|
76
|
+
# Create a local tracking branch if it doesn't exist already
|
77
|
+
unless branch_exists(path, branch)
|
78
|
+
puts "- Creating local tracking branch: #{branch} -> origin/#{branch}"
|
79
|
+
system "cd #{path}; git branch checkout --track #{branch} origin/#{branch}"
|
80
|
+
end
|
81
|
+
|
82
|
+
# Check out the local branch
|
83
|
+
puts "- Checkout local branch: #{branch}"
|
84
|
+
system "cd #{path}; git checkout #{branch}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def update_external(url, path, branch='master')
|
89
|
+
require 'fileutils'
|
90
|
+
if File.directory? "#{path}/.git"
|
91
|
+
`cd #{path}; git pull origin #{branch}`
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def execute(cmd)
|
96
|
+
values = []
|
97
|
+
IO.popen(cmd) do |f|
|
98
|
+
tmp = f.gets
|
99
|
+
values.push(tmp.gsub(/\r/, '').gsub(/\n/, '')) unless tmp.nil?
|
100
|
+
end
|
101
|
+
return $?.exitstatus, values
|
102
|
+
end
|
103
|
+
|
104
|
+
def command_status
|
105
|
+
ok = 0
|
106
|
+
broken = 0
|
107
|
+
$configurations.each do |name, config|
|
108
|
+
branch = config["branch"]
|
109
|
+
url = config["url"]
|
110
|
+
path = config["path"]
|
111
|
+
|
112
|
+
gitBranchExit, gitBranch = execute("cd #{path} && git config \"branch.$(git symbolic-ref HEAD --short).merge\" | sed \"s/refs\\/heads\\///g\"")
|
113
|
+
gitRemoteExit, gitRemote = execute("cd #{path} && git config \"remote.$(git config \"branch.$(git symbolic-ref HEAD --short).remote\").url\"");
|
114
|
+
|
115
|
+
if gitBranchExit != 0 && gitRemoteExit != 0
|
116
|
+
puts " ✗ #{path}: exit code #{gitBranchExit}, #{gitRemoteExit}"
|
117
|
+
broken += 1
|
118
|
+
else
|
119
|
+
if branch == gitBranch[0]
|
120
|
+
if url == gitRemote[0]
|
121
|
+
puts " ✓ #{path}"
|
122
|
+
ok += 1
|
123
|
+
else
|
124
|
+
puts " ✗ #{path} -- expected url '#{url}' but was '#{gitRemote[0]}'"
|
125
|
+
broken +=1
|
126
|
+
end
|
127
|
+
else
|
128
|
+
puts " ✗ #{path} -- expected branch '#{branch}' but was '#{gitBranch[0]}'"
|
129
|
+
broken +=1
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
puts "#{broken > 0 ? "✗" : "✓"} » #{ok} ok • #{broken} broken"
|
134
|
+
end
|
135
|
+
|
136
|
+
def command_add(url, path, branch='master')
|
137
|
+
command_rm(path)
|
138
|
+
`git config -f #{$externals_file} --add external.#{path}.path #{path}`
|
139
|
+
`git config -f #{$externals_file} --add external.#{path}.url #{url}`
|
140
|
+
`git config -f #{$externals_file} --add external.#{path}.branch #{branch}`
|
141
|
+
`echo "#{path}" >> #{$ignore_file}`
|
142
|
+
end
|
143
|
+
|
144
|
+
def command_rm(path)
|
145
|
+
if File.file? $externals_file
|
146
|
+
`git config -f #{$externals_file} --unset external.#{path}.path`
|
147
|
+
`git config -f #{$externals_file} --unset external.#{path}.url`
|
148
|
+
`git config -f #{$externals_file} --unset external.#{path}.branch`
|
149
|
+
`git config -f #{$externals_file} --remove-section external.#{path} > /dev/null 2>&1`
|
150
|
+
File.delete $externals_file if `wc -l #{$externals_file}`.chomp.to_i == 0
|
151
|
+
end
|
152
|
+
if File.file? $ignore_file
|
153
|
+
# Remove entry from .gitignore file
|
154
|
+
`perl -pi -e 's/\\Q#{path.gsub(/\//, '\/')}\\E\n//g' #{$ignore_file}`
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def command_init
|
159
|
+
$configurations.each do |name, config|
|
160
|
+
puts name
|
161
|
+
init_external config["url"], config["path"], config["branch"]
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def command_update
|
166
|
+
$configurations.each do |name, config|
|
167
|
+
update_external config["url"], config["path"], config["branch"]
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def command_cmd(cmd)
|
172
|
+
$configurations.each do |name, config|
|
173
|
+
path = config['path']
|
174
|
+
system("echo #{path}; cd #{path}; #{cmd}")
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def command_list
|
179
|
+
print_configuration
|
180
|
+
end
|
181
|
+
|
182
|
+
load_configuration
|
183
|
+
|
184
|
+
command=ARGV[0]
|
185
|
+
|
186
|
+
case command
|
187
|
+
when "status" then command_status
|
188
|
+
when "add" then command_add ARGV[1], ARGV[2], ARGV[3] || "master"
|
189
|
+
when "rm" then command_rm ARGV[1]
|
190
|
+
when "init" then command_init
|
191
|
+
when "update" then command_update
|
192
|
+
when "cmd" then command_cmd ARGV[1]
|
193
|
+
when "list" then command_list
|
194
|
+
else usage
|
195
|
+
end
|
196
|
+
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: obazoud-git-external
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 17
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 5
|
10
|
+
version: 0.1.5
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Daniel Cestari
|
14
|
+
- Olivier Bazoud
|
15
|
+
- Alastair Harrison
|
16
|
+
autorequire:
|
17
|
+
bindir: bin
|
18
|
+
cert_chain: []
|
19
|
+
|
20
|
+
date: 2012-10-24 00:00:00 Z
|
21
|
+
dependencies: []
|
22
|
+
|
23
|
+
description: Extension for git which adds a command providing similar functionality to git submodules but without attaching each module to a single version
|
24
|
+
email:
|
25
|
+
- olivier.bazoud@gmail.com
|
26
|
+
executables:
|
27
|
+
- git-external
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files: []
|
31
|
+
|
32
|
+
files:
|
33
|
+
- bin/git-external
|
34
|
+
homepage: http://github.com/obazoud/git-external
|
35
|
+
licenses: []
|
36
|
+
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
hash: 3
|
48
|
+
segments:
|
49
|
+
- 0
|
50
|
+
version: "0"
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
requirements: []
|
61
|
+
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 1.8.24
|
64
|
+
signing_key:
|
65
|
+
specification_version: 3
|
66
|
+
summary: Git version of an svn:external, an alternative to Git Submodule
|
67
|
+
test_files: []
|
68
|
+
|