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.
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