git_cli 0.1.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 +7 -0
- data/.gitignore +10 -0
- data/.travis.yml +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +62 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/git_cli.gemspec +33 -0
- data/lib/git_cli.rb +220 -0
- data/lib/git_cli/add_commit.rb +147 -0
- data/lib/git_cli/branch.rb +273 -0
- data/lib/git_cli/clone.rb +42 -0
- data/lib/git_cli/delta.rb +229 -0
- data/lib/git_cli/diff.rb +88 -0
- data/lib/git_cli/git_core.rb +85 -0
- data/lib/git_cli/global.rb +33 -0
- data/lib/git_cli/ignore.rb +79 -0
- data/lib/git_cli/init.rb +65 -0
- data/lib/git_cli/log.rb +96 -0
- data/lib/git_cli/os/linux/utils.rb +62 -0
- data/lib/git_cli/os/macos/.keep +0 -0
- data/lib/git_cli/os/win/.keep +0 -0
- data/lib/git_cli/pull.rb +48 -0
- data/lib/git_cli/push.rb +76 -0
- data/lib/git_cli/repos.rb +117 -0
- data/lib/git_cli/stash.rb +224 -0
- data/lib/git_cli/tags.rb +333 -0
- data/lib/git_cli/version.rb +19 -0
- metadata +115 -0
@@ -0,0 +1,224 @@
|
|
1
|
+
# Copyright (C) 2020 Chris Liaw <chrisliaw@antrapol.com>
|
2
|
+
# Author: Chris Liaw <chrisliaw@antrapol.com>
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
module GitCli
|
20
|
+
module Stash
|
21
|
+
|
22
|
+
# GIT Stash is interesting to facilitate keeping the WIP
|
23
|
+
# on specific branch but have to switch to other branch
|
24
|
+
# due to various reason. i.e. urgent fix, hot patch etc
|
25
|
+
|
26
|
+
#
|
27
|
+
# Save all the temporary changes so branch switch is possible
|
28
|
+
#
|
29
|
+
def stash_changes(msg, include_untracked = true)
|
30
|
+
|
31
|
+
check_vcs
|
32
|
+
|
33
|
+
cmd = []
|
34
|
+
cmd << "cd"
|
35
|
+
cmd << @wsPath
|
36
|
+
cmd << "&&"
|
37
|
+
cmd << @vcs.exe_path
|
38
|
+
cmd << "stash"
|
39
|
+
cmd << "save"
|
40
|
+
|
41
|
+
if not_empty?(msg)
|
42
|
+
# have to escape the message for command line purposes
|
43
|
+
msg2 = msg.gsub("\"","\\\"").gsub("\\","\\\\")
|
44
|
+
cmd << msg2
|
45
|
+
end
|
46
|
+
|
47
|
+
# always include untracked since the stash condition
|
48
|
+
# is played using scenario under development and must
|
49
|
+
# switch branch for any reasons
|
50
|
+
if include_untracked
|
51
|
+
cmd << "--include-untracked"
|
52
|
+
end
|
53
|
+
|
54
|
+
cmdln = cmd.join(" ")
|
55
|
+
log_debug "Stash changes : #{cmdln}"
|
56
|
+
res = os_exec(cmdln) do |st, res|
|
57
|
+
[st.success?, res]
|
58
|
+
end
|
59
|
+
|
60
|
+
end # stash changes
|
61
|
+
|
62
|
+
#
|
63
|
+
# List all saved temporary changes
|
64
|
+
#
|
65
|
+
def stash_list
|
66
|
+
|
67
|
+
check_vcs
|
68
|
+
|
69
|
+
cmd = []
|
70
|
+
cmd << "cd"
|
71
|
+
cmd << @wsPath
|
72
|
+
cmd << "&&"
|
73
|
+
cmd << @vcs.exe_path
|
74
|
+
cmd << "stash list"
|
75
|
+
|
76
|
+
cmdln = cmd.join(" ")
|
77
|
+
log_debug "Stash list : #{cmdln}"
|
78
|
+
res = os_exec(cmdln) do |st, res|
|
79
|
+
if st.success?
|
80
|
+
list = { }
|
81
|
+
res.each_line do |l|
|
82
|
+
ll = l.split(": ")
|
83
|
+
|
84
|
+
# first element is the stash id
|
85
|
+
# 2nd element is the info on branch
|
86
|
+
branch = ll[1].split(" ")[-1]
|
87
|
+
|
88
|
+
|
89
|
+
list[ll[0].strip] = [branch, ll[1..-1].join(": ")]
|
90
|
+
end
|
91
|
+
|
92
|
+
[true, list]
|
93
|
+
else
|
94
|
+
[false, res]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end # stash list
|
99
|
+
|
100
|
+
#
|
101
|
+
# Restore the temporary changes
|
102
|
+
# Regardless which branch are you in
|
103
|
+
#
|
104
|
+
def stash_restore(id = nil)
|
105
|
+
|
106
|
+
check_vcs
|
107
|
+
|
108
|
+
cmd = []
|
109
|
+
cmd << "cd"
|
110
|
+
cmd << @wsPath
|
111
|
+
cmd << "&&"
|
112
|
+
cmd << @vcs.exe_path
|
113
|
+
cmd << "stash apply"
|
114
|
+
|
115
|
+
if not is_empty?(id)
|
116
|
+
cmd << id
|
117
|
+
end
|
118
|
+
|
119
|
+
cmdln = cmd.join(" ")
|
120
|
+
log_debug "Stash apply (restore the saved state) : #{cmdln}"
|
121
|
+
res = os_exec(cmdln) do |st, res|
|
122
|
+
|
123
|
+
[st.success?, res]
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
end # stash restore
|
128
|
+
|
129
|
+
def stash_restore_and_remove(id = nil)
|
130
|
+
|
131
|
+
check_vcs
|
132
|
+
|
133
|
+
cmd = []
|
134
|
+
cmd << "cd"
|
135
|
+
cmd << @wsPath
|
136
|
+
cmd << "&&"
|
137
|
+
cmd << @vcs.exe_path
|
138
|
+
cmd << "stash pop"
|
139
|
+
|
140
|
+
if not is_empty?(id)
|
141
|
+
cmd << id
|
142
|
+
end
|
143
|
+
|
144
|
+
cmdln = cmd.join(" ")
|
145
|
+
log_debug "Stash pop (restore the saved state and delete from list) : #{cmdln}"
|
146
|
+
res = os_exec(cmdln) do |st, res|
|
147
|
+
|
148
|
+
[st.success?, res]
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
end # stash restore
|
153
|
+
|
154
|
+
def stash_to_new_branch(branch, id = nil)
|
155
|
+
|
156
|
+
raise_if_empty(branch, "Branch name must not be empty for stash to branch operation", GitCliException)
|
157
|
+
|
158
|
+
check_vcs
|
159
|
+
|
160
|
+
cmd = []
|
161
|
+
cmd << "cd"
|
162
|
+
cmd << @wsPath
|
163
|
+
cmd << "&&"
|
164
|
+
cmd << @vcs.exe_path
|
165
|
+
cmd << "stash branch"
|
166
|
+
cmd << branch
|
167
|
+
|
168
|
+
if not is_empty?(id)
|
169
|
+
cmd << id
|
170
|
+
end
|
171
|
+
|
172
|
+
cmdln = cmd.join(" ")
|
173
|
+
log_debug "Stash to new branch and delete from list : #{cmdln}"
|
174
|
+
res = os_exec(cmdln) do |st, res|
|
175
|
+
|
176
|
+
[st.success?, res]
|
177
|
+
|
178
|
+
end
|
179
|
+
|
180
|
+
end # stash_to_branch
|
181
|
+
|
182
|
+
def stash_clear
|
183
|
+
|
184
|
+
check_vcs
|
185
|
+
|
186
|
+
cmd = []
|
187
|
+
cmd << "cd"
|
188
|
+
cmd << @wsPath
|
189
|
+
cmd << "&&"
|
190
|
+
cmd << @vcs.exe_path
|
191
|
+
cmd << "stash clear"
|
192
|
+
|
193
|
+
cmdln = cmd.join(" ")
|
194
|
+
log_debug "Clear the stash list (all uncommitted changes lost permanently) : #{cmdln}"
|
195
|
+
res = os_exec(cmdln) do |st, res|
|
196
|
+
[st.success?, res]
|
197
|
+
end
|
198
|
+
|
199
|
+
end # stash clear
|
200
|
+
|
201
|
+
def stash_remove(id = nil)
|
202
|
+
|
203
|
+
check_vcs
|
204
|
+
|
205
|
+
cmd = []
|
206
|
+
cmd << "cd"
|
207
|
+
cmd << @wsPath
|
208
|
+
cmd << "&&"
|
209
|
+
cmd << @vcs.exe_path
|
210
|
+
cmd << "stash drop"
|
211
|
+
if not is_empty?(id)
|
212
|
+
cmd << id
|
213
|
+
end
|
214
|
+
|
215
|
+
cmdln = cmd.join(" ")
|
216
|
+
log_debug "Stash #{is_empty?(id) ? "remove" : "'#{id}' is being removed"} from list (all uncommitted changes lost permanantly): #{cmdln}"
|
217
|
+
res = os_exec(cmdln) do |st, res|
|
218
|
+
[st.success?, res]
|
219
|
+
end
|
220
|
+
|
221
|
+
end # stash_remove
|
222
|
+
|
223
|
+
end
|
224
|
+
end
|
data/lib/git_cli/tags.rb
ADDED
@@ -0,0 +1,333 @@
|
|
1
|
+
# Copyright (C) 2020 Chris Liaw <chrisliaw@antrapol.com>
|
2
|
+
# Author: Chris Liaw <chrisliaw@antrapol.com>
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation, either version 3 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
module GitCli
|
20
|
+
module Tags
|
21
|
+
|
22
|
+
def all_tags
|
23
|
+
|
24
|
+
check_vcs
|
25
|
+
|
26
|
+
cmd = []
|
27
|
+
cmd << "cd"
|
28
|
+
cmd << @wsPath
|
29
|
+
cmd << "&&"
|
30
|
+
cmd << @vcs.exe_path
|
31
|
+
cmd << "tag"
|
32
|
+
|
33
|
+
cmdln = cmd.join(" ")
|
34
|
+
log_debug "List tags : #{cmdln}"
|
35
|
+
res = os_exec(cmdln) do |st, res|
|
36
|
+
|
37
|
+
if st.success?
|
38
|
+
[true, res.strip!]
|
39
|
+
else
|
40
|
+
[false, res]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end # tags
|
45
|
+
|
46
|
+
|
47
|
+
def tag_info(tag, format = "%H|%ad|%an|%s")
|
48
|
+
|
49
|
+
raise_if_empty(tag, "Tag name cannot be empty", GitCliException)
|
50
|
+
|
51
|
+
check_vcs
|
52
|
+
|
53
|
+
tagInfo = { }
|
54
|
+
|
55
|
+
cmd = []
|
56
|
+
cmd << "cd"
|
57
|
+
cmd << @wsPath
|
58
|
+
cmd << "&&"
|
59
|
+
cmd << @vcs.exe_path
|
60
|
+
#cmd << "log -1 --format=%ai"
|
61
|
+
cmd << "show"
|
62
|
+
cmd << tag
|
63
|
+
|
64
|
+
# git show <tag> with format
|
65
|
+
# doesn't really portray the actual date
|
66
|
+
# the creation of tag in history commit list
|
67
|
+
# the date is refers to the commit date,
|
68
|
+
# not the date the tag was created
|
69
|
+
if not_empty?(format)
|
70
|
+
cmd << "--format=\"#{format}\""
|
71
|
+
end
|
72
|
+
|
73
|
+
cmdln = cmd.join(" ")
|
74
|
+
log_debug "Tag '#{tag}' with info : #{cmdln}"
|
75
|
+
res = os_exec(cmdln) do |st, res|
|
76
|
+
[st.success?, res]
|
77
|
+
end
|
78
|
+
|
79
|
+
end # tags
|
80
|
+
|
81
|
+
#def all_tags_with_info(format = "%(refname:short)|%(authordate)|%(authorname)|%(subject)", deli = "|")
|
82
|
+
|
83
|
+
# check_vcs
|
84
|
+
|
85
|
+
# tagInfo = []
|
86
|
+
|
87
|
+
# cmd = []
|
88
|
+
# cmd << "cd"
|
89
|
+
# cmd << @wsPath
|
90
|
+
# cmd << "&&"
|
91
|
+
# cmd << @vcs.exe_path
|
92
|
+
# cmd << "tag"
|
93
|
+
# cmd << "--format=\"#{format}\""
|
94
|
+
|
95
|
+
# cmdln = cmd.join(" ")
|
96
|
+
# log_debug "All tags with info : #{cmdln}"
|
97
|
+
# res = os_exec(cmdln) do |st, res|
|
98
|
+
# if st.success?
|
99
|
+
# res.each_line do |l|
|
100
|
+
# tagInfo << l.split(deli)
|
101
|
+
# end
|
102
|
+
# else
|
103
|
+
# log_error("Date info for tag '#{tt}' error : #{res.strip}")
|
104
|
+
# end
|
105
|
+
# end
|
106
|
+
|
107
|
+
# [true, tagInfo]
|
108
|
+
|
109
|
+
#end # tags
|
110
|
+
|
111
|
+
|
112
|
+
def create_tag(tag, msg = nil, branch= nil)
|
113
|
+
|
114
|
+
raise_if_empty(tag, "Tag name cannot be empty", GitCliException)
|
115
|
+
|
116
|
+
check_vcs
|
117
|
+
|
118
|
+
cmd = []
|
119
|
+
cmd << "cd"
|
120
|
+
cmd << @wsPath
|
121
|
+
cmd << "&&"
|
122
|
+
cmd << @vcs.exe_path
|
123
|
+
cmd << "tag"
|
124
|
+
|
125
|
+
if not_empty?(msg)
|
126
|
+
|
127
|
+
msg2 = msg.gsub("\"","\\\"").gsub("\\","\\\\")
|
128
|
+
|
129
|
+
cmd << "-a"
|
130
|
+
#cmd << "\"#{tag}\""
|
131
|
+
cmd << tag
|
132
|
+
cmd << "-m"
|
133
|
+
cmd << "\"#{msg2}\""
|
134
|
+
|
135
|
+
else
|
136
|
+
cmd << tag
|
137
|
+
end
|
138
|
+
|
139
|
+
if not_empty?(branch)
|
140
|
+
cmd << branch
|
141
|
+
end
|
142
|
+
|
143
|
+
cmdln = cmd.join(" ")
|
144
|
+
log_debug "New tag : #{cmdln}"
|
145
|
+
res = os_exec(cmdln) do |st, res|
|
146
|
+
if st.success?
|
147
|
+
[true, res.strip!]
|
148
|
+
else
|
149
|
+
[false, res]
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
end # create_tag
|
154
|
+
|
155
|
+
def create_tag_from_commit(tag, commit, msg = nil)
|
156
|
+
|
157
|
+
raise_if_empty(tag, "Tag name cannot be empty", GitCliException)
|
158
|
+
raise_if_empty(commit, "Commit ID cannot be empty", GitCliException)
|
159
|
+
|
160
|
+
check_vcs
|
161
|
+
|
162
|
+
cmd = []
|
163
|
+
cmd << "cd"
|
164
|
+
cmd << @wsPath
|
165
|
+
cmd << "&&"
|
166
|
+
cmd << @vcs.exe_path
|
167
|
+
cmd << "tag"
|
168
|
+
|
169
|
+
if not_empty?(msg)
|
170
|
+
|
171
|
+
msg2 = msg.gsub("\"","\\\"").gsub("\\","\\\\")
|
172
|
+
|
173
|
+
cmd << "-a"
|
174
|
+
cmd << tag
|
175
|
+
cmd << "-m"
|
176
|
+
cmd << msg2
|
177
|
+
|
178
|
+
else
|
179
|
+
cmd << "-a"
|
180
|
+
cmd << tag
|
181
|
+
end
|
182
|
+
|
183
|
+
cmd << commit
|
184
|
+
|
185
|
+
cmdln = cmd.join(" ")
|
186
|
+
log_debug "New tag from commit ID : #{cmdln}"
|
187
|
+
res = os_exec(cmdln) do |st, res|
|
188
|
+
if st.success?
|
189
|
+
[true, res.strip!]
|
190
|
+
else
|
191
|
+
[false, res]
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
end # create_tag_from_commit
|
196
|
+
|
197
|
+
def fetch_tag_to_local
|
198
|
+
|
199
|
+
check_vcs
|
200
|
+
#check_repos
|
201
|
+
|
202
|
+
cmd = []
|
203
|
+
cmd << "cd"
|
204
|
+
cmd << @wsPath
|
205
|
+
cmd << "&&"
|
206
|
+
cmd << @vcs.exe_path
|
207
|
+
cmd << "fetch --all --tags"
|
208
|
+
|
209
|
+
cmdln = cmd.join(" ")
|
210
|
+
log_debug "Fetch tags from repository : #{cmdln}"
|
211
|
+
res = os_exec(cmdln) do |st, res|
|
212
|
+
|
213
|
+
if st.success?
|
214
|
+
[true, res.strip!]
|
215
|
+
else
|
216
|
+
[false, res]
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
end # fetch_tag_to_local
|
221
|
+
|
222
|
+
def show_tag_detail(tag, format = nil)
|
223
|
+
|
224
|
+
raise_if_empty(tag, "Tag name cannot be empty", GitCliException)
|
225
|
+
|
226
|
+
check_vcs
|
227
|
+
|
228
|
+
cmd = []
|
229
|
+
cmd << "cd"
|
230
|
+
cmd << @wsPath
|
231
|
+
cmd << "&&"
|
232
|
+
cmd << @vcs.exe_path
|
233
|
+
cmd << "show"
|
234
|
+
cmd << tag
|
235
|
+
|
236
|
+
if not_empty?(format)
|
237
|
+
cmd << "--format=\"#{format}\""
|
238
|
+
end
|
239
|
+
|
240
|
+
cmdln = cmd.join(" ")
|
241
|
+
log_debug "Show tag '#{tag}' #{not_empty?(format) ? "[#{format}]" : ""} : #{cmdln}"
|
242
|
+
res = os_exec(cmdln) do |st, res|
|
243
|
+
if st.success?
|
244
|
+
[true, res.strip!]
|
245
|
+
else
|
246
|
+
[false, res]
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
end # show_tag_detail
|
251
|
+
|
252
|
+
def delete_tag(tag)
|
253
|
+
raise_if_empty(tag, "Tag name cannot be empty", GitCliException)
|
254
|
+
|
255
|
+
check_vcs
|
256
|
+
|
257
|
+
cmd = []
|
258
|
+
cmd << "cd"
|
259
|
+
cmd << @wsPath
|
260
|
+
cmd << "&&"
|
261
|
+
cmd << @vcs.exe_path
|
262
|
+
cmd << "tag -d"
|
263
|
+
cmd << tag
|
264
|
+
|
265
|
+
cmdln = cmd.join(" ")
|
266
|
+
log_debug "Delete tag '#{tag}' : #{cmdln}"
|
267
|
+
res = os_exec(cmdln) do |st, res|
|
268
|
+
if st.success?
|
269
|
+
[true, res.strip!]
|
270
|
+
else
|
271
|
+
[false, res]
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
end # delete_tag
|
276
|
+
|
277
|
+
def delete_remote_tag(repos,tag)
|
278
|
+
|
279
|
+
raise_if_empty(repos, "Repos name cannot be empty", GitCliException)
|
280
|
+
raise_if_empty(tag, "Tag name cannot be empty", GitCliException)
|
281
|
+
|
282
|
+
check_vcs
|
283
|
+
|
284
|
+
cmd = []
|
285
|
+
cmd << "cd"
|
286
|
+
cmd << @wsPath
|
287
|
+
cmd << "&&"
|
288
|
+
cmd << @vcs.exe_path
|
289
|
+
cmd << "push origin --delete"
|
290
|
+
cmd << tag
|
291
|
+
|
292
|
+
cmdln = cmd.join(" ")
|
293
|
+
log_debug "Delete remote tag '#{tag}' at '#{repos}': #{cmdln}"
|
294
|
+
res = os_exec(cmdln) do |st, res|
|
295
|
+
if st.success?
|
296
|
+
[true, res.strip!]
|
297
|
+
else
|
298
|
+
[false, res]
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
end # delete_remote_tag
|
303
|
+
|
304
|
+
def checkout_tag(tag, branch)
|
305
|
+
|
306
|
+
raise_if_empty(tag, "Tag name cannot be empty", GitCliException)
|
307
|
+
|
308
|
+
check_vcs
|
309
|
+
|
310
|
+
cmd = []
|
311
|
+
cmd << "cd"
|
312
|
+
cmd << @wsPath
|
313
|
+
cmd << "&&"
|
314
|
+
cmd << @vcs.exe_path
|
315
|
+
cmd << "checkout"
|
316
|
+
cmd << "tags/#{tag}"
|
317
|
+
cmd << "-b"
|
318
|
+
cmd << branch
|
319
|
+
|
320
|
+
cmdln = cmd.join(" ")
|
321
|
+
log_debug "Checkout tag '#{tag}' into branch '#{branch}': #{cmdln}"
|
322
|
+
res = os_exec(cmdln) do |st, res|
|
323
|
+
if st.success?
|
324
|
+
[true, res.strip!]
|
325
|
+
else
|
326
|
+
[false, res]
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
end # checkout_tag
|
331
|
+
|
332
|
+
end
|
333
|
+
end
|