safedb 0.7.1001 → 0.10.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +50 -3
  3. data/Dockerfile +46 -0
  4. data/Jenkinsfile +45 -0
  5. data/README.md +16 -0
  6. data/Rakefile +2 -2
  7. data/cucumber-test.sh +55 -0
  8. data/lib/cli.rb +20 -7
  9. data/lib/controller/abstract/controller.rb +2 -3
  10. data/lib/controller/access/init.rb +11 -7
  11. data/lib/controller/access/login.rb +0 -2
  12. data/lib/controller/book/commit.rb +1 -0
  13. data/lib/controller/db/obliterate.feature +45 -0
  14. data/lib/controller/db/obliterate.rb +58 -0
  15. data/lib/controller/db/pull.rb +10 -26
  16. data/lib/controller/db/push.rb +29 -321
  17. data/lib/controller/db/{remote.rb → remote-github-keypair.rb} +11 -6
  18. data/lib/controller/db/remote-github-token.rb +69 -0
  19. data/lib/controller/db/state.rb +63 -0
  20. data/lib/controller/query/publish.rb +27 -0
  21. data/lib/controller/requirer.rb +0 -1
  22. data/lib/manual/git-interaction.md +176 -0
  23. data/lib/manual/remote.md +0 -1
  24. data/lib/model/book.rb +13 -1
  25. data/lib/model/checkin.feature +15 -27
  26. data/lib/model/content.rb +25 -27
  27. data/lib/model/indices.rb +35 -8
  28. data/lib/model/state_evolve.rb +21 -0
  29. data/lib/model/text_chunk.rb +1 -1
  30. data/lib/utils/extend/string.rb +28 -0
  31. data/lib/utils/git/gitflow.rb +565 -0
  32. data/lib/utils/git/github.rb +69 -0
  33. data/lib/utils/identity/machine.id.rb +2 -2
  34. data/lib/utils/keys/keypair.rb +93 -0
  35. data/lib/utils/logs/logger.rb +3 -4
  36. data/lib/utils/time/timestamp.rb +2 -0
  37. data/lib/version.rb +1 -1
  38. data/pod-image-builder.yaml +27 -0
  39. data/pod-image-safetty.yaml +18 -0
  40. data/safedb.gemspec +1 -6
  41. metadata +17 -64
  42. data/genius-decision.txt +0 -25
  43. data/lib/controller/db/model_git_service.rb +0 -399
  44. data/lib/plugin/github.rb +0 -53
  45. 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
- Etc.getlogin,
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
- Etc.getlogin(),
122
+ ENV[ "USER" ],
123
123
  Socket.gethostname()
124
124
  ].join
125
125