gpack 2.0.0 → 2.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.
- checksums.yaml +4 -4
- data/LICENSE +674 -0
- data/README.rst +157 -0
- data/lib/gpack/config/headers.rb +5 -0
- data/lib/gpack/core/GitCollection.rb +154 -0
- data/lib/gpack/core/GitReference.rb +366 -0
- data/lib/gpack/core/gpack.rb +94 -0
- data/lib/gpack/core/gpack_readme.rb +160 -0
- data/lib/gpack/core/parallel.rb +570 -0
- data/lib/gpack/core/parse_repos.rb +73 -0
- data/lib/gpack/core/ssh.rb +33 -0
- data/lib/gpack_readme.rb +154 -0
- data/test/test_gpack.rb +10 -0
- metadata +13 -1
data/README.rst
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
=====
|
|
2
|
+
GitPack v2.0
|
|
3
|
+
=====
|
|
4
|
+
|
|
5
|
+
From https://github.com/GitPack/GitPackRuby
|
|
6
|
+
|
|
7
|
+
Ruby Implementation of git repository manager. Conceptually simular to a tool like bundle, gradel, ect. GitPack handles the distrubuting of Git repositories without being tied to a specific language; although it does use ruby to execute commands. GitPack specifically is intended to control multiple git repository dependancies on a project where it is required that multiple user's point to the same commit/branch/tag. GitPack simplifies the usage of Git and can be especially beneficial when working with teams where not every user knows how to manage a git repository. GitPack uses a single file "GpackRepos" to specifiy the URL and local destination of repositories that it should manage.
|
|
8
|
+
|
|
9
|
+
* Clones multiple repositories in parallel.
|
|
10
|
+
* Controls read-only permissions on cloned repositories.
|
|
11
|
+
* Pulls multiple repositoires in parallel.
|
|
12
|
+
* Easy clean of repositories that do not have a clean git status.
|
|
13
|
+
* Submodule compatible
|
|
14
|
+
|
|
15
|
+
Structure
|
|
16
|
+
-----
|
|
17
|
+
* ./gpack - The main exectuable. GitPack is self updating and downloads the latest ver. of master from this repository.
|
|
18
|
+
* ./GpackRepos - The main file that GitPack uses to store information about remote repositories URL, the local desitinations where the repositories should be cloned, and user configuration options like read-only, SSH keys, ect. This file is in YAML format
|
|
19
|
+
* ./.gpacklock - Used to store the repository read-only status.
|
|
20
|
+
|
|
21
|
+
Dependancies
|
|
22
|
+
-----
|
|
23
|
+
* Tested in Ruby 2.3
|
|
24
|
+
|
|
25
|
+
Setup
|
|
26
|
+
-----
|
|
27
|
+
Download the gpack bash script to a local directory and make the file executable:
|
|
28
|
+
|
|
29
|
+
.. code::
|
|
30
|
+
|
|
31
|
+
wget https://raw.githubusercontent.com/GitPack/GitPack/master/gpack
|
|
32
|
+
chmod u+x ./gpack
|
|
33
|
+
|
|
34
|
+
Or install via ruby gems
|
|
35
|
+
|
|
36
|
+
.. code::
|
|
37
|
+
|
|
38
|
+
gem install gpack
|
|
39
|
+
|
|
40
|
+
Add repos to GpackRepos file using gpack, an example is shown below:
|
|
41
|
+
|
|
42
|
+
.. code::
|
|
43
|
+
|
|
44
|
+
./gpack add git@github.com:GitPack/GitPack.git ./GitPack
|
|
45
|
+
|
|
46
|
+
Basic Usage
|
|
47
|
+
-----
|
|
48
|
+
|
|
49
|
+
Installs all repos in GpackRepos file:
|
|
50
|
+
|
|
51
|
+
.. code::
|
|
52
|
+
|
|
53
|
+
./gpack install
|
|
54
|
+
|
|
55
|
+
Update installed repos in GpackRepos file:
|
|
56
|
+
|
|
57
|
+
.. code::
|
|
58
|
+
|
|
59
|
+
./gpack update
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
GpackRepos
|
|
63
|
+
----------
|
|
64
|
+
|
|
65
|
+
.. code-block:: bash
|
|
66
|
+
|
|
67
|
+
test1:
|
|
68
|
+
url: git@github.com:GitPack/TestRepo1.git
|
|
69
|
+
localdir: ./repos/test1
|
|
70
|
+
branch: master
|
|
71
|
+
lock: true
|
|
72
|
+
|
|
73
|
+
test2:
|
|
74
|
+
url: git@github.com:GitPack/TestRepo2.git
|
|
75
|
+
localdir: ./repos/test2
|
|
76
|
+
branch: master
|
|
77
|
+
lock: false
|
|
78
|
+
|
|
79
|
+
test3:
|
|
80
|
+
url: git@github.com:GitPack/TestRepo3.git
|
|
81
|
+
localdir: ./repos/test3
|
|
82
|
+
branch: master
|
|
83
|
+
lock: false
|
|
84
|
+
|
|
85
|
+
test3_hash:
|
|
86
|
+
url: git@github.com:GitPack/TestRepo3.git
|
|
87
|
+
localdir: ./repos/test3_hash
|
|
88
|
+
branch: b41e58af7
|
|
89
|
+
lock: false
|
|
90
|
+
|
|
91
|
+
test1_tag:
|
|
92
|
+
url: git@github.com:GitPack/TestRepo1.git
|
|
93
|
+
localdir: ./repos/test1_tag
|
|
94
|
+
branch: v2.0
|
|
95
|
+
lock: false
|
|
96
|
+
|
|
97
|
+
# Options for Configuration
|
|
98
|
+
# config:
|
|
99
|
+
# lock: true # Option to disable read-only by default
|
|
100
|
+
# remote_key: http://some.valid.url # Use an external ssh key
|
|
101
|
+
# ssh_command: ssh -v # Custom SSH arguments passed to $GIT_SSH_COMMAND
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
Core Commands
|
|
106
|
+
-------------
|
|
107
|
+
|
|
108
|
+
**gpack cmd [-f] [-nogui] [-persist] [-s]**
|
|
109
|
+
* -f,--force: Force operation
|
|
110
|
+
* -s,--single: Single threaded, useful for debug
|
|
111
|
+
* -n,--nogui: Do not pop up xterm windows
|
|
112
|
+
* -p,--persist: Keep xterm windows open even if command is successful
|
|
113
|
+
* -i: Force install (applies only to update command)
|
|
114
|
+
|
|
115
|
+
**add [url] [directory] [branch]**
|
|
116
|
+
Adds a repo to the GpackRepos file given ssh URL and local directory
|
|
117
|
+
relative to current directory
|
|
118
|
+
**check**
|
|
119
|
+
Checks if all repos are clean and match GpackRepos
|
|
120
|
+
**status**
|
|
121
|
+
Runs through each repo and reports the result of git status
|
|
122
|
+
**help**
|
|
123
|
+
Displays this message
|
|
124
|
+
**install**
|
|
125
|
+
Clones repos in repo directory
|
|
126
|
+
-nogui doesn't open terminals when installing
|
|
127
|
+
**uninstall**
|
|
128
|
+
Removes all local repositories listed in the Repositories File
|
|
129
|
+
Add -f to force remove all repositories
|
|
130
|
+
**reinstall**
|
|
131
|
+
The same as running uninstall then reinstall
|
|
132
|
+
**list**
|
|
133
|
+
List all repos in GpackRepos file
|
|
134
|
+
**lock**
|
|
135
|
+
Makes repo read-only, removes from .gpacklock file
|
|
136
|
+
**unlock**
|
|
137
|
+
Allows writing to repo, appends to .gpacklock file
|
|
138
|
+
**update [-i] [-f]**
|
|
139
|
+
Updates the repositories -f will install if not already installed
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
Details
|
|
143
|
+
-----------
|
|
144
|
+
* Maintains a clean local repository directory by parsing GpackRepos for user-defined repositores that they wish to clone.
|
|
145
|
+
* By default, all cloned repositories have no write access.
|
|
146
|
+
|
|
147
|
+
Future Improvements
|
|
148
|
+
-----
|
|
149
|
+
* GitPack is not Git LFS compatible at the moment. Merge requests with this feature would be accepted.
|
|
150
|
+
* Add command is not implemented
|
|
151
|
+
* Allow GitPack commands to operate on a per-repository basis
|
|
152
|
+
* Lock/Unlock of individual repositores. (Python version has this)
|
|
153
|
+
|
|
154
|
+
Developers
|
|
155
|
+
-----
|
|
156
|
+
* Andrew Porter https://github.com/AndrewRPorter
|
|
157
|
+
* Aaron Cook https://github.com/cookacounty
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
|
|
2
|
+
$RAISE_WARNING = false
|
|
3
|
+
|
|
4
|
+
class GitCollection
|
|
5
|
+
attr_accessor :refs
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@refs = []
|
|
9
|
+
end
|
|
10
|
+
def add_ref(ref)
|
|
11
|
+
@refs << ref
|
|
12
|
+
end
|
|
13
|
+
def print()
|
|
14
|
+
puts "="*40+"\n\tGit Reference Summary\n"+"="*40
|
|
15
|
+
@refs.each do |ref|
|
|
16
|
+
ref.print()
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
def archive()
|
|
20
|
+
puts "\nCreating archives of local Repositories....."
|
|
21
|
+
raise_warning = ref_loop(refs) { |ref|
|
|
22
|
+
ref.archive
|
|
23
|
+
}
|
|
24
|
+
if raise_warning
|
|
25
|
+
puts "\n"+("="*60+"\nWARNING DURING CLONING!\n\tSome repositories already existed and failed checks.\n\tReview this log or run 'gpack check' to see detailed information\n"+"="*60).color(Colors::RED)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
def clone()
|
|
29
|
+
puts "\nCloning Repositories....."
|
|
30
|
+
raise_warning = ref_loop(refs) { |ref|
|
|
31
|
+
ref.clone
|
|
32
|
+
}
|
|
33
|
+
if raise_warning
|
|
34
|
+
puts "\n"+("="*60+"\nWARNING DURING CLONING!\n\tSome repositories already existed and failed checks.\n\tReview this log or run 'gpack check' to see detailed information\n"+"="*60).color(Colors::RED)
|
|
35
|
+
end
|
|
36
|
+
print()
|
|
37
|
+
check()
|
|
38
|
+
end
|
|
39
|
+
def rinse()
|
|
40
|
+
puts "\nRinsing Repositories....."
|
|
41
|
+
raise_warning = ref_loop(refs) { |ref|
|
|
42
|
+
ref.rinse
|
|
43
|
+
}
|
|
44
|
+
if raise_warning
|
|
45
|
+
puts ("\n"+"="*60+"\nWARNING DURING Rinse!\n"+"="*60).color(Colors::RED)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
def check()
|
|
49
|
+
puts "\nChecking Local Repositories....."
|
|
50
|
+
raise_warning = ref_loop(refs,true) { |ref|
|
|
51
|
+
ref.check
|
|
52
|
+
}
|
|
53
|
+
if raise_warning
|
|
54
|
+
puts "\n"+("="*60+"\nWARNINGS FOUND DURING CHECK!\n\tReview this log to see detailed information\n" \
|
|
55
|
+
"\tThe following commands can be run to help debug:\n" \
|
|
56
|
+
"\t\tgpack status #Shows the current git status\n" \
|
|
57
|
+
"\t\tgpack rinse #Removes all local changes and untracked files,use with caution\n" \
|
|
58
|
+
+"="*60).color(Colors::RED)
|
|
59
|
+
else
|
|
60
|
+
puts "\n"+("All checks passed!").color(Colors::GREEN)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
def status()
|
|
64
|
+
puts "\nStatus of Local Repositories....."
|
|
65
|
+
raise_warning = ref_loop(refs,true) { |ref|
|
|
66
|
+
ref.status
|
|
67
|
+
}
|
|
68
|
+
if raise_warning
|
|
69
|
+
puts "\n"+("="*60+"\nWARNINGS FOUND DURING CHECK!\n\tReview this log to see detailed information\n"+"="*60).color(Colors::RED)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
def update()
|
|
73
|
+
print()
|
|
74
|
+
puts "\nUpdating Repositories.....\n\n"
|
|
75
|
+
puts "Please be patient, this can take some time if pulling large commits.....".color(Colors::GREEN)
|
|
76
|
+
raise_warning = ref_loop(refs) { |ref|
|
|
77
|
+
ref.update()
|
|
78
|
+
}
|
|
79
|
+
if raise_warning
|
|
80
|
+
puts "\n"+("="*60+"\nWARNING DURING UPDATE!\n\tSome repositories failed checks and were not updated.\n\tReview this log or run 'gpack check' to see detailed information\n"+"="*60).color(Colors::RED)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
def remove()
|
|
84
|
+
puts "This will force remove repositories and repopulate. Any local data will be lost!!!\nContinue (y/n)"
|
|
85
|
+
if $SETTINGS["core"]["force"] == true
|
|
86
|
+
do_remove = true
|
|
87
|
+
else
|
|
88
|
+
cont = $stdin.gets.chomp
|
|
89
|
+
do_remove = cont == "y"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
if do_remove
|
|
93
|
+
puts "\nRemoving Local Repositories....."
|
|
94
|
+
|
|
95
|
+
raise_warning = ref_loop(refs) { |ref|
|
|
96
|
+
ref.remove()
|
|
97
|
+
}
|
|
98
|
+
`rm -f .gpackunlock`
|
|
99
|
+
else
|
|
100
|
+
puts "Abort Uninstall"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
if raise_warning
|
|
104
|
+
puts "\n"+("="*60+"\nWARNINGS FOUND DURING REMOVAL!\n\tReview this log to see detailed information\n"+"="*60).color(Colors::RED)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
def set_writeable(tf)
|
|
108
|
+
ref_loop(refs) { |ref|
|
|
109
|
+
ref.set_writeable(tf)
|
|
110
|
+
}
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def ref_loop(refs, parallel_override=false)
|
|
115
|
+
if $SETTINGS["core"]["parallel"] && !parallel_override
|
|
116
|
+
read, write = IO.pipe
|
|
117
|
+
Parallel.map(@refs) do |ref|
|
|
118
|
+
|
|
119
|
+
# Set up standard output as a StringIO object.
|
|
120
|
+
old_stdout = $stdout
|
|
121
|
+
foo = StringIO.new
|
|
122
|
+
$stdout = foo
|
|
123
|
+
|
|
124
|
+
raise_warning = yield(ref)
|
|
125
|
+
write.puts raise_warning
|
|
126
|
+
|
|
127
|
+
$stdout = old_stdout
|
|
128
|
+
puts foo.string
|
|
129
|
+
|
|
130
|
+
end
|
|
131
|
+
write.close
|
|
132
|
+
read_data = read.read
|
|
133
|
+
#puts read_data
|
|
134
|
+
if read_data.index("true")
|
|
135
|
+
raise_warning = true
|
|
136
|
+
end
|
|
137
|
+
else
|
|
138
|
+
raise_warning = false
|
|
139
|
+
@refs.each do |ref|
|
|
140
|
+
|
|
141
|
+
ret_warning = yield(ref)
|
|
142
|
+
if ret_warning
|
|
143
|
+
raise_warning = true
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
return raise_warning
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
end
|
|
154
|
+
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
module HasProperties
|
|
2
|
+
attr_accessor :props
|
|
3
|
+
attr_accessor :require_attrs
|
|
4
|
+
|
|
5
|
+
def has_properties *args
|
|
6
|
+
@props = args
|
|
7
|
+
instance_eval { attr_reader *args }
|
|
8
|
+
instance_eval { attr_writer *args }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def has_required *args
|
|
12
|
+
@require_attrs = args
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.included base
|
|
16
|
+
base.extend self
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def initialize(args)
|
|
20
|
+
|
|
21
|
+
# Attributes required when defining a GitReference
|
|
22
|
+
require_attrs = self.class.require_attrs
|
|
23
|
+
|
|
24
|
+
# Check that all the required
|
|
25
|
+
args.each do |k,v|
|
|
26
|
+
require_attrs = require_attrs - [k]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
if require_attrs.any?
|
|
30
|
+
raise "Must include attributes #{require_attrs} in GitReference definition"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
args.each {|k,v|
|
|
34
|
+
instance_variable_set "@#{k}", v if self.class.props.member?(k)
|
|
35
|
+
} if args.is_a? Hash
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class GitReference
|
|
41
|
+
include HasProperties
|
|
42
|
+
|
|
43
|
+
has_properties :url, :localdir, :branch, :readonly
|
|
44
|
+
has_required :url, :localdir, :branch
|
|
45
|
+
|
|
46
|
+
def initialize args
|
|
47
|
+
# Non-Required defaults
|
|
48
|
+
@readonly = true
|
|
49
|
+
|
|
50
|
+
super
|
|
51
|
+
end
|
|
52
|
+
def clone()
|
|
53
|
+
|
|
54
|
+
#Clone the Git Repository
|
|
55
|
+
checks_failed = false
|
|
56
|
+
|
|
57
|
+
#check if directory already exists
|
|
58
|
+
if local_exists
|
|
59
|
+
puts "Cloning Warning - Directory #{localdir} already exists! Running checks instead"
|
|
60
|
+
checks_failed = self.check()
|
|
61
|
+
else
|
|
62
|
+
status = syscmd("git clone -b #{branch} #{url} #{localdir} --recursive",true,false)
|
|
63
|
+
self.checkout
|
|
64
|
+
self.set_writeable(false) if @readonly
|
|
65
|
+
|
|
66
|
+
if status != 0
|
|
67
|
+
checks_failed = true
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
return checks_failed
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def update()
|
|
76
|
+
force_clone = $SETTINGS["core"]["force"] || $SETTINGS["core"]["install"]
|
|
77
|
+
command_failed = false
|
|
78
|
+
# Returns true if falure
|
|
79
|
+
if local_exists
|
|
80
|
+
checks_failed = self.check(true) # TODO, should this fail if branch is wrong?
|
|
81
|
+
if !checks_failed
|
|
82
|
+
puts "Updating local repository #{@localdir}"
|
|
83
|
+
self.set_writeable(true) if @readonly
|
|
84
|
+
syscmd("git fetch origin",true)
|
|
85
|
+
self.checkout
|
|
86
|
+
syscmd("git submodule update --init --recursive")
|
|
87
|
+
self.set_writeable(false) if @readonly
|
|
88
|
+
command_failed = false
|
|
89
|
+
else
|
|
90
|
+
command_failed = true
|
|
91
|
+
end
|
|
92
|
+
elsif force_clone
|
|
93
|
+
self.clone
|
|
94
|
+
command_failed = false
|
|
95
|
+
else
|
|
96
|
+
command_failed = true
|
|
97
|
+
end
|
|
98
|
+
return command_failed
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def checkout()
|
|
102
|
+
if is_branch()
|
|
103
|
+
checkout_cmd = "checkout -B #{@branch} origin/#{@branch}" # Create a local branch
|
|
104
|
+
else
|
|
105
|
+
checkout_cmd = "checkout #{@branch}" # Direct checkout the tag/comit
|
|
106
|
+
end
|
|
107
|
+
syscmd("git #{checkout_cmd} && git submodule update --init --recursive")
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def set_writeable(tf)
|
|
111
|
+
|
|
112
|
+
if tf
|
|
113
|
+
puts "Setting #{@localdir} to writable"
|
|
114
|
+
perms = "u+w"
|
|
115
|
+
else
|
|
116
|
+
puts "Setting #{@localdir} to read only"
|
|
117
|
+
perms = "a-w"
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
file_paths = []
|
|
121
|
+
ignore_paths = []
|
|
122
|
+
if local_exists()
|
|
123
|
+
Find.find(@localdir) do |path|
|
|
124
|
+
# Ignore .git folder
|
|
125
|
+
if path.match(/.*\/.git$/) || path.match(/.*\/.git\/.*/)
|
|
126
|
+
ignore_paths << path
|
|
127
|
+
else
|
|
128
|
+
file_paths << path
|
|
129
|
+
#FileUtils.chmod 'a-w', path
|
|
130
|
+
FileUtils.chmod(perms,path) if File.exist?(path)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# Useful for debug
|
|
136
|
+
#puts "IGNORED PATHS\n"+ignore_paths.to_s
|
|
137
|
+
#puts "FOUND_PATHS\n"+file_paths.to_s
|
|
138
|
+
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def check(skip_branch=false)
|
|
142
|
+
#Check integrety
|
|
143
|
+
# Check that URL matches
|
|
144
|
+
# Check that branch matches
|
|
145
|
+
# Check that there are no local changes "clean" state
|
|
146
|
+
check_git_writable()
|
|
147
|
+
|
|
148
|
+
puts "\nRunning checks on local repository #{@localdir}"
|
|
149
|
+
checks_failed = false
|
|
150
|
+
if local_exists
|
|
151
|
+
if !skip_branch
|
|
152
|
+
if is_branch()
|
|
153
|
+
bname = @branch
|
|
154
|
+
else
|
|
155
|
+
bname = rev_parse(@branch)
|
|
156
|
+
end
|
|
157
|
+
branch_valid = local_branch() == bname
|
|
158
|
+
if !branch_valid
|
|
159
|
+
puts "\tFAIL - Check branch matches #{@branch} rev #{bname}".color(Colors::RED)
|
|
160
|
+
puts "\t\tLocal Branch abbrev : '#{rev_parse("HEAD",true)}'"
|
|
161
|
+
puts "\t\tLocal Branch SHA : '#{rev_parse("HEAD")}'"
|
|
162
|
+
puts "\t\tSpecified Branch : '#{@branch}'"
|
|
163
|
+
puts "\t\tSpecified Branch abbrev : '#{rev_parse(@branch)}'"
|
|
164
|
+
puts "\t\tSpecified Branch SHA : '#{rev_parse(@branch,true)}'"
|
|
165
|
+
checks_failed = true
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
if local_url() == @url
|
|
170
|
+
#puts "\tPASS - Check remote url matches #{@url}"
|
|
171
|
+
else
|
|
172
|
+
puts "\tFAIL - Check remote url matches #{@url}".color(Colors::RED)
|
|
173
|
+
puts "\t\tLocal URL #{local_url()}'"
|
|
174
|
+
puts "\t\tRemote URL #{@url}'"
|
|
175
|
+
checks_failed = true
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
if local_clean()
|
|
179
|
+
#puts "\tPASS - Check local repository clean"
|
|
180
|
+
else
|
|
181
|
+
puts "\tFAIL - Check local repository clean".color(Colors::RED)
|
|
182
|
+
checks_failed = true
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
if !checks_failed
|
|
186
|
+
puts "PASS - All checks on local repository #{@localdir}".color(Colors::GREEN)
|
|
187
|
+
else
|
|
188
|
+
puts "CHECK FAILURE on local repository #{@localdir}. See previous log for info on which check failed".color(Colors::RED)
|
|
189
|
+
end
|
|
190
|
+
else
|
|
191
|
+
puts "\tFAIL - Check local repository exists".color(Colors::RED)
|
|
192
|
+
checks_failed = true
|
|
193
|
+
end
|
|
194
|
+
return checks_failed
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def syscmd(cmd,open_xterm=false,cd_first=true)
|
|
198
|
+
if cd_first
|
|
199
|
+
cmd = "cd #{@localdir} && #{cmd}"
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
#Pass env var to Open3
|
|
203
|
+
ssh_cmd = $SETTINGS["ssh"]["cmd"]
|
|
204
|
+
if ssh_cmd
|
|
205
|
+
args = {"GIT_SSH_COMMAND" => ssh_cmd}
|
|
206
|
+
puts "custom ssh"
|
|
207
|
+
else
|
|
208
|
+
args = {}
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
if open_xterm && $SETTINGS["gui"]["show"]
|
|
212
|
+
if $SETTINGS["gui"]["persist"]
|
|
213
|
+
hold_opt = "-hold"
|
|
214
|
+
end
|
|
215
|
+
if ssh_cmd
|
|
216
|
+
cmd = "echo 'GIT_SSH_COMMAND $GIT_SSH_COMMAND' ; #{cmd}"
|
|
217
|
+
end
|
|
218
|
+
cmd = "xterm #{hold_opt} -geometry 90x30 -e \"#{cmd} || echo 'Command Failed, see log above. Press CTRL+C to close window' && sleep infinity\""
|
|
219
|
+
end
|
|
220
|
+
cmd_id = Digest::SHA1.hexdigest(cmd).to_s[0..4]
|
|
221
|
+
|
|
222
|
+
stdout_str,stderr_str,status = Open3.capture3(args,cmd)
|
|
223
|
+
|
|
224
|
+
puts "="*30+"COMMAND ID #{cmd_id}"+"="*28+"\n"
|
|
225
|
+
puts ("#{cmd}").color(Colors::YELLOW)
|
|
226
|
+
if stdout_str != "" || stderr_str != ""
|
|
227
|
+
puts "="*30+"COMMAND #{cmd_id} LOG START"+"="*28+"\n"
|
|
228
|
+
puts stderr_str
|
|
229
|
+
puts stdout_str
|
|
230
|
+
puts "="*30+"COMMAND #{cmd_id} LOG END"+"="*30+"\n"
|
|
231
|
+
end
|
|
232
|
+
status
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def localcmd(cmd_str)
|
|
236
|
+
return `cd #{@localdir} && #{cmd_str}`.chomp
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def remove()
|
|
240
|
+
force = $SETTINGS["core"]["force"]
|
|
241
|
+
command_failed = false
|
|
242
|
+
if force || !self.check
|
|
243
|
+
puts "Removing local repository #{@localdir}"
|
|
244
|
+
self.set_writeable(true) if @readonly || force
|
|
245
|
+
syscmd("rm -rf #{@localdir}",false,false)
|
|
246
|
+
command_failed = false
|
|
247
|
+
else
|
|
248
|
+
command_failed = true
|
|
249
|
+
end
|
|
250
|
+
return command_failed
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def rinse()
|
|
254
|
+
force = $SETTINGS["core"]["force"]
|
|
255
|
+
if !@readonly && !force
|
|
256
|
+
puts "Error with repository #{@localdir}\n\t Repositories can only be rinsed when in readonly mode"
|
|
257
|
+
command_failed = true
|
|
258
|
+
else
|
|
259
|
+
self.set_writeable(true) if @readonly
|
|
260
|
+
status = syscmd( \
|
|
261
|
+
"git fetch origin && " \
|
|
262
|
+
"git clean -xdff && " \
|
|
263
|
+
"git reset --hard && " \
|
|
264
|
+
"git submodule foreach --recursive git clean -xdff && " \
|
|
265
|
+
"git submodule foreach --recursive git reset --hard && " \
|
|
266
|
+
"git submodule update --init --recursive")
|
|
267
|
+
self.checkout
|
|
268
|
+
self.set_writeable(false) if @readonly
|
|
269
|
+
if !status
|
|
270
|
+
command_failed = true
|
|
271
|
+
puts "Rinse command failed for repo #{@localdir}, check log"
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
return command_failed
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def archive()
|
|
280
|
+
#Archive the Git Repository
|
|
281
|
+
|
|
282
|
+
checks_failed = false
|
|
283
|
+
|
|
284
|
+
#check if directory already exists
|
|
285
|
+
if !self.check()
|
|
286
|
+
command_failed = true
|
|
287
|
+
else
|
|
288
|
+
git_ref = local_rev
|
|
289
|
+
dirname = @localdir.match( /\/([^\/]*)\s*$/)[1].chomp
|
|
290
|
+
tarname = "#{dirname}_#{git_ref}.tar.gz"
|
|
291
|
+
tarcmd = "tar -zcvf #{tarname} #{@localdir} > /dev/null"
|
|
292
|
+
syscmd(tarcmd)
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
return command_failed
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def check_git_writable()
|
|
299
|
+
# Make sure .git folder is writable
|
|
300
|
+
|
|
301
|
+
gitdirs = `find #{localdir} -type d -name ".git"`
|
|
302
|
+
gitdirs.each_line do |dir|
|
|
303
|
+
dir.chomp!
|
|
304
|
+
if !File.writable?(dir)
|
|
305
|
+
puts "Warning, .git folder #{dir} was found read-only. Automatically setting it to writable"
|
|
306
|
+
syscmd("chmod ug+w -R #{dir}")
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
def status
|
|
311
|
+
self.print()
|
|
312
|
+
syscmd("git status && echo 'Git Branch' && git branch && echo 'Git SHA' && git rev-parse HEAD")
|
|
313
|
+
return false
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def is_branch()
|
|
317
|
+
#check if branch ID is a branch or a tag/commit
|
|
318
|
+
return system("cd #{localdir} && git show-ref -q --verify refs/remotes/origin/#{@branch}")
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def local_branch()
|
|
322
|
+
if is_branch()
|
|
323
|
+
bname = rev_parse("HEAD",true)
|
|
324
|
+
else
|
|
325
|
+
bname = rev_parse("HEAD")
|
|
326
|
+
end
|
|
327
|
+
return bname
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def rev_parse(rev,abbrev=false)
|
|
331
|
+
if abbrev
|
|
332
|
+
rp = localcmd("git rev-parse --abbrev-ref #{rev}")
|
|
333
|
+
else
|
|
334
|
+
rp = localcmd("git rev-parse #{rev}")
|
|
335
|
+
end
|
|
336
|
+
return rp
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
def local_url()
|
|
340
|
+
urlname = localcmd("git config --get remote.origin.url")
|
|
341
|
+
return urlname
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def local_rev()
|
|
345
|
+
revname = localcmd("git rev-parse --short HEAD")
|
|
346
|
+
return revname
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def local_clean()
|
|
350
|
+
clean = localcmd("git status --porcelain")
|
|
351
|
+
return clean == "" # Empty string means it's clean
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
def local_exists()
|
|
355
|
+
if Dir.exists?(@localdir)
|
|
356
|
+
return true
|
|
357
|
+
else
|
|
358
|
+
return false
|
|
359
|
+
end
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
def print()
|
|
363
|
+
puts "Reference #{@url}\n\tlocaldir-#{@localdir}\n\tbranch-#{@branch}\n\treadonly-#{@readonly}"
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
end
|