safedb 0.7.1001 → 0.10.5
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/CONTRIBUTING.md +50 -3
- data/Dockerfile +46 -0
- data/Jenkinsfile +45 -0
- data/README.md +16 -0
- data/Rakefile +2 -2
- data/cucumber-test.sh +55 -0
- data/lib/cli.rb +20 -7
- data/lib/controller/abstract/controller.rb +2 -3
- data/lib/controller/access/init.rb +11 -7
- data/lib/controller/access/login.rb +0 -2
- data/lib/controller/book/commit.rb +1 -0
- data/lib/controller/db/obliterate.feature +45 -0
- data/lib/controller/db/obliterate.rb +58 -0
- data/lib/controller/db/pull.rb +10 -26
- data/lib/controller/db/push.rb +29 -321
- data/lib/controller/db/{remote.rb → remote-github-keypair.rb} +11 -6
- data/lib/controller/db/remote-github-token.rb +69 -0
- data/lib/controller/db/state.rb +63 -0
- data/lib/controller/query/publish.rb +27 -0
- data/lib/controller/requirer.rb +0 -1
- data/lib/manual/git-interaction.md +176 -0
- data/lib/manual/remote.md +0 -1
- data/lib/model/book.rb +13 -1
- data/lib/model/checkin.feature +15 -27
- data/lib/model/content.rb +25 -27
- data/lib/model/indices.rb +35 -8
- data/lib/model/state_evolve.rb +21 -0
- data/lib/model/text_chunk.rb +1 -1
- data/lib/utils/extend/string.rb +28 -0
- data/lib/utils/git/gitflow.rb +565 -0
- data/lib/utils/git/github.rb +69 -0
- data/lib/utils/identity/machine.id.rb +2 -2
- data/lib/utils/keys/keypair.rb +93 -0
- data/lib/utils/logs/logger.rb +3 -4
- data/lib/utils/time/timestamp.rb +2 -0
- data/lib/version.rb +1 -1
- data/pod-image-builder.yaml +27 -0
- data/pod-image-safetty.yaml +18 -0
- data/safedb.gemspec +1 -6
- metadata +17 -64
- data/genius-decision.txt +0 -25
- data/lib/controller/db/model_git_service.rb +0 -399
- data/lib/plugin/github.rb +0 -53
- data/lib/utils/store/github.rb +0 -27
@@ -0,0 +1,565 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
module SafeDb
|
4
|
+
|
5
|
+
|
6
|
+
# Provision the git branch involved in our present working directory.
|
7
|
+
# The [present directory] may not relate to version control at all or
|
8
|
+
# it may relate to the master or other branch in the source mgt tool.
|
9
|
+
class GitFlow
|
10
|
+
|
11
|
+
|
12
|
+
# Make the folder at the given path a git repository if it is not
|
13
|
+
# one already. If the folder is already under git management then
|
14
|
+
# this call has no effect.
|
15
|
+
#
|
16
|
+
# @param repo_path [String] folder path to the desired git repository
|
17
|
+
def self.init repo_path
|
18
|
+
|
19
|
+
git_init_cmd = "git init #{repo_path}"
|
20
|
+
log.info(x) { "[git] add command => #{git_init_cmd}" }
|
21
|
+
cmd_output = %x[#{git_init_cmd}];
|
22
|
+
|
23
|
+
log.info(x) { "[git] initializing git repository at path #{repo_path}" }
|
24
|
+
log.info(x) { "[git] init command output : #{cmd_output}" }
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
# Log the files (names and/or content) that either do not come under the
|
31
|
+
# wing of git or have been added to git repository management but are yet
|
32
|
+
# to be committed into the repository. Also an files are logged that have
|
33
|
+
# either been updated, deleted or moved.
|
34
|
+
#
|
35
|
+
# @param repo_path [String] folder path to the desired git repository
|
36
|
+
# @param by_line [Boolean]
|
37
|
+
# if set to true the log will list the changed lines fronted either
|
38
|
+
# with a plus or a minus sign. False will just list the file names
|
39
|
+
def self.list( repo_path, by_line=false )
|
40
|
+
|
41
|
+
path_to_dot_git = File.join( repo_path, ".git" )
|
42
|
+
line_by_line = by_line ? "-v" : ""
|
43
|
+
|
44
|
+
git_log_cmd = "git --git-dir=#{path_to_dot_git} --work-tree=#{repo_path} status #{line_by_line}"
|
45
|
+
log.info(x) { "[git] status command => #{git_log_cmd}" }
|
46
|
+
git_log_output = %x[#{git_log_cmd}]
|
47
|
+
|
48
|
+
git_log_output.log_debug if by_line
|
49
|
+
git_log_output.log_info unless by_line
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
|
55
|
+
# Stage all files that evoke some kind of difference between the
|
56
|
+
# working copy and the local git repository so that they can all
|
57
|
+
# be committed.
|
58
|
+
#
|
59
|
+
# Files that will be staged by this method can be
|
60
|
+
#
|
61
|
+
# - newly created files (that do not match gitignore patterns)
|
62
|
+
# - modified files that are already under git version management
|
63
|
+
# - files deleted in the working copy but not removed from the repository
|
64
|
+
# - files renamed in the same folder or with their path changed too
|
65
|
+
# - all the above but found recursively under the root repository path
|
66
|
+
#
|
67
|
+
# @param repo_path [String] folder path to the desired git repository
|
68
|
+
def self.stage repo_path
|
69
|
+
|
70
|
+
path_to_dot_git = File.join( repo_path, ".git" )
|
71
|
+
git_add_cmd = "git --git-dir=#{path_to_dot_git} --work-tree=#{repo_path} add -A"
|
72
|
+
log.info(x) { "[git] add command => #{git_add_cmd}" }
|
73
|
+
%x[#{git_add_cmd}];
|
74
|
+
log.info(x) { "[git] has recursively added resources to version management." }
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
# Commit all changes to the local git repo at the stated folder path
|
81
|
+
# with the parameter commit message.
|
82
|
+
#
|
83
|
+
# @param repo_path [String] folder path to the desired git repository
|
84
|
+
# @param commit_msg [String] the commit message to post to the repo
|
85
|
+
def self.commit( repo_path, commit_msg )
|
86
|
+
|
87
|
+
log.info(x) { "[git] commit msg => #{commit_msg}" }
|
88
|
+
path_to_dot_git = File.join( repo_path, ".git" )
|
89
|
+
git_commit_cmd = "git --git-dir=#{path_to_dot_git} --work-tree=#{repo_path} commit -m \"#{commit_msg}\";"
|
90
|
+
log.info(x) { "[git] commit command => #{git_commit_cmd}" }
|
91
|
+
%x[#{git_commit_cmd}];
|
92
|
+
log.info(x) { "[git] has committed resources into the local repository." }
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
# Configure the user.email and user.name properties for the git software
|
99
|
+
# to use alongside its other commands. This must always be done before a
|
100
|
+
# git commit command is issued.
|
101
|
+
#
|
102
|
+
# @param repo_path [String] folder path to the desired git repository
|
103
|
+
# @param user_email [String] the email address of the user owning the repository
|
104
|
+
# @param user_name [String] the full name of the user owning the repository
|
105
|
+
def self.config( repo_path, user_email, user_name )
|
106
|
+
|
107
|
+
log.info(x) { "[git] local config for user.email => #{user_email}" }
|
108
|
+
log.info(x) { "[git] local config for user.name => #{user_name}" }
|
109
|
+
path_to_dot_git = File.join( repo_path, ".git" )
|
110
|
+
git_config_email_cmd = "git --git-dir=#{path_to_dot_git} --work-tree=#{repo_path} config --local user.email \"#{user_email}\";"
|
111
|
+
git_config_name_cmd = "git --git-dir=#{path_to_dot_git} --work-tree=#{repo_path} config --local user.name \"#{user_name}\";"
|
112
|
+
log.info(x) { "[git] configure user.email command => #{git_config_email_cmd}" }
|
113
|
+
log.info(x) { "[git] configure user.name command => #{git_config_name_cmd}" }
|
114
|
+
%x[#{git_config_email_cmd}];
|
115
|
+
%x[#{git_config_name_cmd}];
|
116
|
+
log.info(x) { "[git] has locally configured the user.email and user.name properties." }
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
# Remove a specific file from git management and also delete the
|
123
|
+
# working copy version of the file.
|
124
|
+
#
|
125
|
+
# @param repo_path [String] folder path to the desired git repository
|
126
|
+
# @param file_path [String] file to remove from the repo and working copy
|
127
|
+
def self.del_file( repo_path, file_path )
|
128
|
+
|
129
|
+
path_to_dot_git = File.join( repo_path, ".git" )
|
130
|
+
git_rm_cmd = "git --git-dir=#{path_to_dot_git} --work-tree=#{repo_path} rm #{file_path}"
|
131
|
+
log.info(x) { "[git] file remove command => #{git_rm_cmd}" }
|
132
|
+
%x[#{git_rm_cmd}];
|
133
|
+
log.info(x) { "[git] has removed #{file_path} from repo and working copy." }
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
|
139
|
+
|
140
|
+
# Add a specific file that exists in the working copy to the git
|
141
|
+
# version controller.
|
142
|
+
#
|
143
|
+
# @param repo_path [String] folder path to the desired git repository
|
144
|
+
# @param file_path [String] file to add to the git version controller
|
145
|
+
def self.add_file( repo_path, file_path )
|
146
|
+
|
147
|
+
path_to_dot_git = File.join( repo_path, ".git" )
|
148
|
+
git_add_cmd = "git --git-dir=#{path_to_dot_git} --work-tree=#{repo_path} add #{file_path}"
|
149
|
+
log.info(x) { "[git] single file add command => #{git_add_cmd}" }
|
150
|
+
%x[#{git_add_cmd}];
|
151
|
+
log.info(x) { "[git] has added #{file_path} into the git repository." }
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
|
157
|
+
|
158
|
+
# Add the parameter remote origin URL to the git repository at the
|
159
|
+
# stated path. This method assumes the origin url is non-sensitive
|
160
|
+
# and logs it. No passwords or access tokens expected in the url.
|
161
|
+
#
|
162
|
+
# Use in conjunction with set_push_origin_url to create a push url
|
163
|
+
# that is different from the fetch url.
|
164
|
+
#
|
165
|
+
# @param repo_path [String] folder path to the desired git repository
|
166
|
+
# @param origin_url [String] the URL to the remote origin to add
|
167
|
+
def self.add_origin_url repo_path, origin_url
|
168
|
+
|
169
|
+
path_to_dot_git = File.join( repo_path, ".git" )
|
170
|
+
git_add_origin_loggable_cmd = "git --git-dir=#{path_to_dot_git} --work-tree=#{repo_path} remote add origin"
|
171
|
+
git_add_origin_cmd = "#{git_add_origin_loggable_cmd} #{origin_url}"
|
172
|
+
log.info(x) { "[git] add origin command without url => #{git_add_origin_loggable_cmd}" }
|
173
|
+
%x[#{git_add_origin_cmd}];
|
174
|
+
log.info(x) { "[git] has added a remote origin url." }
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
|
180
|
+
# Set only the origin url to push to. This command leaves the fetch
|
181
|
+
# url as is. The push_origin_url is assumed sensitive as it may
|
182
|
+
# contain either passwords or access tokens. As such it is not logged.
|
183
|
+
#
|
184
|
+
# The remote origin must be set before calling this method. If no origin
|
185
|
+
# is set this will throw a "no origin" error.
|
186
|
+
#
|
187
|
+
# @param repo_path [String] folder path to the desired git repository
|
188
|
+
# @param push_origin_url [String] the push URL of the remote origin
|
189
|
+
def self.set_push_origin_url repo_path, push_origin_url
|
190
|
+
|
191
|
+
path_to_dot_git = File.join( repo_path, ".git" )
|
192
|
+
git_loggable_cmd = "git --git-dir=#{path_to_dot_git} --work-tree=#{repo_path} remote set-url --push origin"
|
193
|
+
git_set_push_origin_url_cmd = "#{git_loggable_cmd} #{push_origin_url}"
|
194
|
+
log.info(x) { "[git] set push origin url command without url => #{git_loggable_cmd}" }
|
195
|
+
%x[#{git_set_push_origin_url_cmd}];
|
196
|
+
log.info(x) { "[git] has set the remote origin url for pushing." }
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
|
201
|
+
|
202
|
+
# Push the commit bundles to the remote git repository.
|
203
|
+
#
|
204
|
+
# @param repo_path [String] folder path to the desired git repository
|
205
|
+
def self.push repo_path
|
206
|
+
|
207
|
+
path_to_dot_git = File.join( repo_path, ".git" )
|
208
|
+
git_push_cmd = "git --git-dir=#{path_to_dot_git} --work-tree=#{repo_path} push origin master"
|
209
|
+
log.info(x) { "[git] push command => #{git_push_cmd}" }
|
210
|
+
system git_push_cmd
|
211
|
+
log.info(x) { "[git] has pushed outstanding commit bundles to the remote backend repository." }
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
|
216
|
+
|
217
|
+
|
218
|
+
|
219
|
+
|
220
|
+
|
221
|
+
|
222
|
+
|
223
|
+
# -- ------------------------------------------------- -- #
|
224
|
+
# -- Return the branch name of a local git repository. -- #
|
225
|
+
# -- ------------------------------------------------- -- #
|
226
|
+
# -- Parameter -- #
|
227
|
+
# -- path_to_dot_git : local path to the .git folder -- #
|
228
|
+
# -- -- #
|
229
|
+
# -- Dependencies and Assumptions -- #
|
230
|
+
# -- git is installed on the machine -- #
|
231
|
+
# -- ------------------------------------------------- -- #
|
232
|
+
def self.wc_branch_name path_to_dot_git
|
233
|
+
|
234
|
+
cmd = "git --git-dir=#{path_to_dot_git} branch";
|
235
|
+
branch_names = %x[#{cmd}];
|
236
|
+
branch_names.each_line do |line|
|
237
|
+
return line[2, line.length].strip if line.start_with?('*')
|
238
|
+
end
|
239
|
+
raise ArgumentError.new "No branch name starts with asterix.\n#{cmd}\n#{branch_names}\n"
|
240
|
+
|
241
|
+
end
|
242
|
+
|
243
|
+
|
244
|
+
# -- ------------------------------------------------- -- #
|
245
|
+
# -- Get the remote origin url of a git working copy. -- #
|
246
|
+
# -- ------------------------------------------------- -- #
|
247
|
+
# -- Parameter -- #
|
248
|
+
# -- path_to_dot_git : local path to .git folder -- #
|
249
|
+
# -- -- #
|
250
|
+
# -- Dependencies and Assumptions -- #
|
251
|
+
# -- git is installed on the machine -- #
|
252
|
+
# -- working copy exists and has remote origin -- #
|
253
|
+
# -- ------------------------------------------------- -- #
|
254
|
+
def self.wc_origin_url path_to_dot_git
|
255
|
+
|
256
|
+
cmd = "git --git-dir=#{path_to_dot_git} config --get remote.origin.url"
|
257
|
+
url = %x[#{cmd}];
|
258
|
+
raise ArgumentError.new "No remote origin url.\n#{cmd}\n" if url.nil?
|
259
|
+
|
260
|
+
return url.strip
|
261
|
+
|
262
|
+
end
|
263
|
+
|
264
|
+
|
265
|
+
# -- -------------------------------------------------- -- #
|
266
|
+
# -- Get the uncut revision of a git repo working copy. -- #
|
267
|
+
# -- -------------------------------------------------- -- #
|
268
|
+
# -- Parameter -- #
|
269
|
+
# -- path_to_dot_git : local path to .git folder -- #
|
270
|
+
# -- -- #
|
271
|
+
# -- Dependencies and Assumptions -- #
|
272
|
+
# -- git is installed on the machine -- #
|
273
|
+
# -- working copy exists and has remote origin -- #
|
274
|
+
# -- -------------------------------------------------- -- #
|
275
|
+
def self.wc_revision_uncut path_to_dot_git
|
276
|
+
|
277
|
+
log.info(x) { "##### GitFlow path to dot git is => #{path_to_dot_git}" }
|
278
|
+
repo_url = wc_origin_url path_to_dot_git
|
279
|
+
log.info(x) { "##### The GitFlow repo url is => #{repo_url}" }
|
280
|
+
|
281
|
+
## Bug HERE - On Ubuntu the branch name is like => (HEAD detached at 067f9a3)
|
282
|
+
## Bug HERE - This creates a failure of => sh: 1: Syntax error: "(" unexpected
|
283
|
+
## Bug HERE - The unexpected failure occurs in the ls-remote command below
|
284
|
+
## Bug HERE - So hardcoding this to "master" for now
|
285
|
+
# branch_name = wc_branch_name path_to_dot_git
|
286
|
+
branch_name = "master"
|
287
|
+
|
288
|
+
log.info(x) { "##### The GitFlow branch name is => #{branch_name}" }
|
289
|
+
cmd = "git ls-remote #{repo_url} ls-remote -b #{branch_name}"
|
290
|
+
log.info(x) { "##### The GitFlow get dirty rev command is => #{cmd}" }
|
291
|
+
dirty_revision = %x[#{cmd}];
|
292
|
+
log.info(x) { "##### The dirty revision is => #{dirty_revision}" }
|
293
|
+
return dirty_revision.partition("refs/heads").first.strip;
|
294
|
+
|
295
|
+
end
|
296
|
+
|
297
|
+
|
298
|
+
# -- -------------------------------------------------- -- #
|
299
|
+
# -- Get brief revision of repo from working copy path. -- #
|
300
|
+
# -- -------------------------------------------------- -- #
|
301
|
+
# -- Parameter -- #
|
302
|
+
# -- path_to_dot_git : local path to .git folder -- #
|
303
|
+
# -- -- #
|
304
|
+
# -- Dependencies and Assumptions -- #
|
305
|
+
# -- we return the first 7 revision chars -- #
|
306
|
+
# -- git is installed on the machine -- #
|
307
|
+
# -- working copy exists and has remote origin -- #
|
308
|
+
# -- -------------------------------------------------- -- #
|
309
|
+
def self.wc_revision path_to_dot_git
|
310
|
+
|
311
|
+
log.info(x) { "GitFlow path to dot git is => #{path_to_dot_git}" }
|
312
|
+
Throw.if_not_exists path_to_dot_git
|
313
|
+
|
314
|
+
uncut_revision = wc_revision_uncut path_to_dot_git
|
315
|
+
log.info(x) { "GitFlow uncut full revision is => #{uncut_revision}" }
|
316
|
+
|
317
|
+
# -- --------------------------------------------------------------------- -- #
|
318
|
+
# -- Gits [short revision] hash has 7 chars. Note 4 is the usable minimum. -- #
|
319
|
+
# -- For usage in stamps where space comes at a premium - 6 chars will do. -- #
|
320
|
+
# -- --------------------------------------------------------------------- -- #
|
321
|
+
ref_length = 7
|
322
|
+
return "r" + uncut_revision[0..(ref_length - 1)];
|
323
|
+
|
324
|
+
end
|
325
|
+
|
326
|
+
|
327
|
+
# -- -------------------------------------------------- -- #
|
328
|
+
# -- Clone the branch of a local git repo working copy. -- #
|
329
|
+
# -- -------------------------------------------------- -- #
|
330
|
+
# -- Parameter -- #
|
331
|
+
# -- src_gitpath : local path to .git folder -- #
|
332
|
+
# -- new_wc_path : path to new non-existent dir -- #
|
333
|
+
# -- -- #
|
334
|
+
# -- Dependencies and Assumptions -- #
|
335
|
+
# -- git is installed on the machine -- #
|
336
|
+
# -- working copy exists and has remote origin -- #
|
337
|
+
# -- -------------------------------------------------- -- #
|
338
|
+
def self.do_clone_wc path_to_dot_git, path_to_new_dir
|
339
|
+
|
340
|
+
# -- ----------------------------------------------------------- -- #
|
341
|
+
# -- Why clone from a working copy (instead of a remote url). -- #
|
342
|
+
# -- ----------------------------------------------------------- -- #
|
343
|
+
# -- -- #
|
344
|
+
# -- When actively [DEVELOPING] an eco plugin and you want to -- #
|
345
|
+
# -- -- #
|
346
|
+
# -- 1 - [test] the behaviour without a git commit/git push -- #
|
347
|
+
# -- 2 - test whatever [branch] the working copy is now at -- #
|
348
|
+
# -- -- #
|
349
|
+
# -- This use case requires us to clone from a working copy. -- #
|
350
|
+
# -- -- #
|
351
|
+
# -- ----------------------------------------------------------- -- #
|
352
|
+
|
353
|
+
### Bug here - see getting branch name issue
|
354
|
+
### Bug here - see getting branch name issue
|
355
|
+
### Bug here - see getting branch name issue
|
356
|
+
### Bug here - see getting branch name issue
|
357
|
+
### branch_name = wc_branch_name path_to_dot_git
|
358
|
+
branch_name = "master"
|
359
|
+
##### cmd = "git clone #{path_to_dot_git} -b #{branch_name} #{path_to_new_dir}"
|
360
|
+
##### cmd = "git clone #{path_to_dot_git} -b #{branch_name} #{path_to_new_dir}"
|
361
|
+
##### cmd = "git clone #{path_to_dot_git} -b #{branch_name} #{path_to_new_dir}"
|
362
|
+
cmd = "git clone #{path_to_dot_git} #{path_to_new_dir}"
|
363
|
+
clone_output = %x[#{cmd}];
|
364
|
+
|
365
|
+
log.info(x) { "[gitflow] cloning working copy" }
|
366
|
+
log.info(x) { "[gitflow] repo branch name : #{branch_name}" }
|
367
|
+
log.info(x) { "[gitflow] src dot git path : #{path_to_dot_git}" }
|
368
|
+
log.info(x) { "[gitflow] new wc dir path : #{path_to_new_dir}" }
|
369
|
+
log.info(x) { "[gitflow] git clone command : #{cmd}" }
|
370
|
+
log.info(x) { "[gitflow] git clone output : #{clone_output}" }
|
371
|
+
|
372
|
+
end
|
373
|
+
|
374
|
+
|
375
|
+
# --
|
376
|
+
# -- Clone a remote repository at the specified [url] into
|
377
|
+
# -- a [NON-EXISTENT] folder path.
|
378
|
+
# --
|
379
|
+
# -- ---------------------------------
|
380
|
+
# -- What is a Non Existent Dir Path?
|
381
|
+
# -- ---------------------------------
|
382
|
+
# --
|
383
|
+
# -- The parent directory of a non existent folder path
|
384
|
+
# -- must [exist] whilst the full path itself does not.
|
385
|
+
# -- The clone operation will create the final folder in
|
386
|
+
# -- the path and then it [puts] the repository contents
|
387
|
+
# -- within it.
|
388
|
+
# --
|
389
|
+
# -- -----------
|
390
|
+
# -- Parameters
|
391
|
+
# -- -----------
|
392
|
+
# --
|
393
|
+
# -- repo_url : url ends in dot git f-slash
|
394
|
+
# -- clone_dir : path to new non-existent dir
|
395
|
+
# --
|
396
|
+
# -- -----------------------------
|
397
|
+
# -- Dependencies and Assumptions
|
398
|
+
# -- -----------------------------
|
399
|
+
# --
|
400
|
+
# -- git is installed on the machine
|
401
|
+
# -- repo exists and is publicly readable
|
402
|
+
# -- the master branch is he one to clone
|
403
|
+
# -- the current Dir.pwd() is writeable
|
404
|
+
# --
|
405
|
+
def self.do_clone_repo repo_url, non_existent_path
|
406
|
+
|
407
|
+
cmd = "git clone #{repo_url} #{non_existent_path}"
|
408
|
+
clone_output = %x[#{cmd}];
|
409
|
+
|
410
|
+
log.info(x) { "[gitflow] cloning remote repository" }
|
411
|
+
log.info(x) { "[gitflow] git repository url : #{repo_url}" }
|
412
|
+
log.info(x) { "[gitflow] git clone dir path : #{nickname non_existent_path}" }
|
413
|
+
log.info(x) { "[gitflow] git clone command : #{cmd}" }
|
414
|
+
log.info(x) { "[gitflow] git clone output : #{clone_output}" }
|
415
|
+
|
416
|
+
end
|
417
|
+
|
418
|
+
|
419
|
+
# -- ----------------------------------------------------- -- #
|
420
|
+
# -- Clone [many] git repositories given an array of urls -- #
|
421
|
+
# -- along with a corresponding array of the working copy -- #
|
422
|
+
# -- folder names and a [parental] base (offset) folder. -- #
|
423
|
+
# -- ----------------------------------------------------- -- #
|
424
|
+
# -- Parameter -- #
|
425
|
+
# -- repo_urls : array of git repository urls -- #
|
426
|
+
# -- base_names : array of cloned repo base names -- #
|
427
|
+
# -- parent_dir : path to local [parent] folder -- #
|
428
|
+
# -- -- #
|
429
|
+
# -- Dependencies and Assumptions -- #
|
430
|
+
# -- arrays have equiv corresponding entries -- #
|
431
|
+
# -- parent dir is created if not exists -- #
|
432
|
+
# -- repos exist and are publicly readable -- #
|
433
|
+
# -- master branches are the ones to clone -- #
|
434
|
+
# -- ----------------------------------------------------- -- #
|
435
|
+
def self.do_clone_repos repo_urls, base_names, parent_dir
|
436
|
+
|
437
|
+
Dir.mkdir parent_dir unless File.exists? parent_dir
|
438
|
+
Throw.if_not_found parent_dir, "clone repos"
|
439
|
+
|
440
|
+
repo_urls.each_with_index do | repo_url, repo_index |
|
441
|
+
|
442
|
+
git_url = repo_url if repo_url.end_with? @@url_postfix
|
443
|
+
git_url = "#{repo_url}#{@@url_postfix}" unless repo_url.end_with? @@url_postfix
|
444
|
+
|
445
|
+
proj_folder = File.join parent_dir, base_names[repo_index]
|
446
|
+
|
447
|
+
log.info(x) { "[clone repos] proj [index] => #{repo_index}" }
|
448
|
+
log.info(x) { "[clone repos] repo url 1st => #{repo_url}" }
|
449
|
+
log.info(x) { "[clone repos] repo url 2nd => #{git_url}" }
|
450
|
+
log.info(x) { "[clone repos] project name => #{base_names[repo_index]}" }
|
451
|
+
log.info(x) { "[clone repos] project path => #{proj_folder}" }
|
452
|
+
|
453
|
+
GitFlow.do_clone_repo git_url, proj_folder
|
454
|
+
|
455
|
+
end
|
456
|
+
|
457
|
+
end
|
458
|
+
|
459
|
+
|
460
|
+
# -- ------------------------------------------------ -- #
|
461
|
+
# -- Move assets from a git repo to a local zip file. -- #
|
462
|
+
# -- ------------------------------------------------ -- #
|
463
|
+
# -- -- #
|
464
|
+
# -- Parameter -- #
|
465
|
+
# -- repo_url : the url of the git repository -- #
|
466
|
+
# -- path_offset : FWD-SLASH ENDED PATH in repo -- #
|
467
|
+
# -- target_dir : the target folder for new zip -- #
|
468
|
+
# -- zip_filename : extensionless name of the zip -- #
|
469
|
+
# -- -- #
|
470
|
+
# -- Return -- #
|
471
|
+
# -- path to the zip file created in a tmp folder -- #
|
472
|
+
# -- -- #
|
473
|
+
# -- ------------------------------------------------ -- #
|
474
|
+
# -- Dependencies and Assumptions -- #
|
475
|
+
# -- ------------------------------------------------ -- #
|
476
|
+
# -- -- #
|
477
|
+
# -- END PATH OFFSET WITH A FORWARD SLASH -- #
|
478
|
+
# -- IF NO OFFSET SEND "/" for path_offset -- #
|
479
|
+
# -- git is installed on the machine -- #
|
480
|
+
# -- the repo exists with path offset -- #
|
481
|
+
# -- the master branch is archived -- #
|
482
|
+
# -- name is unique as used to create a dir -- #
|
483
|
+
# -- -- #
|
484
|
+
# -- ------------------------------------------------ -- #
|
485
|
+
def self.git2zip repo_url, path_offset, target_dir, zip_basename
|
486
|
+
|
487
|
+
log.info(x) { "[git2zip] ------------------------------------------- -- #" }
|
488
|
+
log.info(x) { "[git2zip] archiving repo assets at path offset -- #" }
|
489
|
+
log.info(x) { "[git2zip] ------------------------------------------- -- #" }
|
490
|
+
log.info(x) { "[git2zip] git repository url : #{repo_url}" }
|
491
|
+
log.info(x) { "[git2zip] slash tail dir offset : #{path_offset}" }
|
492
|
+
log.info(x) { "[git2zip] target zip directory : #{target_dir}" }
|
493
|
+
log.info(x) { "[git2zip] zip file [base] name : #{zip_basename}" }
|
494
|
+
|
495
|
+
clone_dir = File.join Dir.tmpdir(), zip_basename
|
496
|
+
do_clone_repo repo_url, clone_dir
|
497
|
+
dot_git_path = File.join clone_dir, ".git"
|
498
|
+
dst_zip_path = File.join target_dir, "#{zip_basename}.zip"
|
499
|
+
|
500
|
+
the_offset = path_offset
|
501
|
+
the_offset = "" if path_offset.length == 1
|
502
|
+
cmd = "git --git-dir=#{dot_git_path} archive -o #{dst_zip_path} HEAD:#{the_offset}"
|
503
|
+
clone_output = %x[#{cmd}];
|
504
|
+
|
505
|
+
log.info(x) { "[git2zip] tmp clone src folder : #{clone_dir}" }
|
506
|
+
log.info(x) { "[git2zip] cloned dot git path : #{dot_git_path}" }
|
507
|
+
log.info(x) { "[git2zip] target zip full path : #{dst_zip_path}" }
|
508
|
+
log.info(x) { "[git2zip] git archive command : #{cmd}" }
|
509
|
+
log.info(x) { "[git2zip] ------------------------------------------- -- #" }
|
510
|
+
log.info(x) { "#{clone_output}" }
|
511
|
+
log.info(x) { "[git2zip] ------------------------------------------- -- #" }
|
512
|
+
|
513
|
+
return dst_zip_path
|
514
|
+
|
515
|
+
end
|
516
|
+
|
517
|
+
|
518
|
+
# -- ------------------------------------------------- -- #
|
519
|
+
# -- Return an array of simple file names in the repo. -- #
|
520
|
+
# -- ------------------------------------------------- -- #
|
521
|
+
# -- Parameter -- #
|
522
|
+
# -- repo_url : the url of the repository to read -- #
|
523
|
+
# -- -- #
|
524
|
+
# -- Dependencies and Assumptions -- #
|
525
|
+
# -- we are not interested in folders -- #
|
526
|
+
# -- trawl is recursive (infinite depth) -- #
|
527
|
+
# -- git is installed on the machine -- #
|
528
|
+
# -- ------------------------------------------------- -- #
|
529
|
+
def self.file_names repo_url
|
530
|
+
|
531
|
+
random_text = SecureRandom.urlsafe_base64(12).delete("-_").downcase
|
532
|
+
cloned_name = "eco.repo.clone.#{random_text}"
|
533
|
+
cloned_path = File.join Dir.tmpdir(), cloned_name
|
534
|
+
|
535
|
+
do_clone_repo repo_url, cloned_path
|
536
|
+
dot_git_path = File.join cloned_path, ".git"
|
537
|
+
|
538
|
+
cmd = "git --git-dir=#{dot_git_path} ls-tree -r master --name-only"
|
539
|
+
filename_lines = %x[#{cmd}];
|
540
|
+
names_list = Array.new
|
541
|
+
filename_lines.each_line do |line|
|
542
|
+
names_list.push line.strip
|
543
|
+
end
|
544
|
+
|
545
|
+
log.info(x) { "[git2files] ----------------------------------------------" }
|
546
|
+
log.info(x) { "[git2files] [#{names_list.length}] files in [#{repo_url}]" }
|
547
|
+
log.info(x) { "[git2files] ----------------------------------------------" }
|
548
|
+
log.info(x) { "[git2files] Random Text : #{random_text}" }
|
549
|
+
log.info(x) { "[git2files] Cloned Name : #{cloned_name}" }
|
550
|
+
log.info(x) { "[git2files] Cloned Path : #{cloned_path}" }
|
551
|
+
log.info(x) { "[git2files] Repo Folder : #{dot_git_path}" }
|
552
|
+
log.info(x) { "[git2files] Reading Cmd : #{cmd}" }
|
553
|
+
log.info(x) { "[git2files] ----------------------------------------------" }
|
554
|
+
pp names_list
|
555
|
+
log.info(x) { "[git2files] ----------------------------------------------" }
|
556
|
+
|
557
|
+
return names_list
|
558
|
+
|
559
|
+
end
|
560
|
+
|
561
|
+
|
562
|
+
end
|
563
|
+
|
564
|
+
end
|
565
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
module SafeDb
|
4
|
+
|
5
|
+
|
6
|
+
# The Github class uses the REST API to talk to Github and create, query,
|
7
|
+
# change and delete assets within a specified hosted git repository.
|
8
|
+
#
|
9
|
+
# Note that you can ply the new github repository with a SSH public key
|
10
|
+
# so that those who know the corresponding private key can post to it. To do
|
11
|
+
# this a repository ID in the format user_name/repository_name must be
|
12
|
+
# provided.
|
13
|
+
#
|
14
|
+
# repository_id = "#{github_user[:login]}/#{repository_name}"
|
15
|
+
# github_client.add_deploy_key( repository_id, "key description", repo_public_key )
|
16
|
+
#
|
17
|
+
class Github
|
18
|
+
|
19
|
+
|
20
|
+
# Create a github git repository when given an access token and the
|
21
|
+
# required repository name.
|
22
|
+
#
|
23
|
+
# @param github_access_token [String] hexadecimal github access token
|
24
|
+
# @param repository_name [String] name of he non-existent repository to create
|
25
|
+
# @return [String] name of the github user
|
26
|
+
def self.create_repo( github_access_token, repository_name )
|
27
|
+
|
28
|
+
require "etc"
|
29
|
+
require "socket"
|
30
|
+
require "octokit"
|
31
|
+
|
32
|
+
github_client = Octokit::Client.new( :access_token => github_access_token )
|
33
|
+
github_user = github_client.user
|
34
|
+
repo_creator = "#{ENV[ "USER" ]}@#{Socket.gethostname()}"
|
35
|
+
repo_description = "This github repository was auto-created by safedb.net to be a remote database backend on behalf of #{repo_creator} on #{TimeStamp.readable()}."
|
36
|
+
repo_homepage = "https://github.com/devops4me/safedb.net/"
|
37
|
+
|
38
|
+
puts ""
|
39
|
+
puts "Repository Name => #{repository_name}"
|
40
|
+
puts "Github Company => #{github_user[:company]}"
|
41
|
+
puts "Account Owner => #{github_user[:name]}"
|
42
|
+
puts "Github User ID => #{github_user[:id]}"
|
43
|
+
puts "Github Username => #{github_user[:login]}"
|
44
|
+
|
45
|
+
puts "Creation Entity => #{repo_creator}"
|
46
|
+
puts "Repo Descriptor => #{repo_description}"
|
47
|
+
puts "Repo Homepage => #{repo_homepage}"
|
48
|
+
puts ""
|
49
|
+
|
50
|
+
options_hash = {
|
51
|
+
:description => repo_description,
|
52
|
+
:repo_homepage => repo_homepage,
|
53
|
+
:private => false,
|
54
|
+
:has_issues => false,
|
55
|
+
:has_wiki => false,
|
56
|
+
:has_downloads => false,
|
57
|
+
:auto_init => false
|
58
|
+
}
|
59
|
+
|
60
|
+
github_client.create_repository( repository_name, options_hash )
|
61
|
+
return github_user[:login]
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
@@ -45,7 +45,7 @@ module SafeDb
|
|
45
45
|
require 'socket'
|
46
46
|
|
47
47
|
identity_text = [
|
48
|
-
|
48
|
+
ENV[ "USER" ],
|
49
49
|
get_machine_id(),
|
50
50
|
Socket.gethostname()
|
51
51
|
].join.reverse
|
@@ -119,7 +119,7 @@ module SafeDb
|
|
119
119
|
identity_text =
|
120
120
|
[
|
121
121
|
get_bootup_id(),
|
122
|
-
|
122
|
+
ENV[ "USER" ],
|
123
123
|
Socket.gethostname()
|
124
124
|
].join
|
125
125
|
|