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
@@ -1,399 +0,0 @@
1
- #!/usr/bin/ruby
2
-
3
- module SafeDb
4
-
5
- module Store
6
-
7
-
8
- # -- ------------------------------------------------------------------- -- #
9
- # -- Provision the git branch involved in our present working directory. -- #
10
- # -- The [present directory] may not relate to version control at all or -- #
11
- # -- it may relate to the master or other branch in the source mgt tool. -- #
12
- # -- ------------------------------------------------------------------- -- #
13
- class GitFlow
14
-
15
- @@url_postfix = ".git/"
16
-
17
- # --
18
- # -- Check in whatever has changed in the local repository
19
- # -- at the path stated in the first parameter.
20
- # --
21
- # -- The text in the second parameter helps to distinguish
22
- # -- what was to be pushed up and forms part of the git
23
- # -- commit message.
24
- # --
25
- def self.push repo_root_dir, what_changed_string, time_stamp
26
-
27
- dot_git_path = File.join repo_root_dir, ".git"
28
- Throw.if_not_exists dot_git_path
29
-
30
- Dir.chdir repo_root_dir
31
-
32
- git_diff_cmd = "git status -vv; echo;"
33
- git_diff_output = %x[#{git_diff_cmd}]
34
- git_diff_output.log_lines
35
-
36
- git_add_cmd = "git add -A; echo;"
37
- git_add_output = %x[#{git_add_cmd}]
38
- git_add_output.log_lines
39
-
40
- git_commit_cmd = "git commit -m \"Writing #{what_changed_string} at #{time_stamp}.\";"
41
- git_commit_output = %x[#{git_commit_cmd}]
42
- git_commit_output.log_lines
43
-
44
- # --
45
- # -- This command may require input (username/password) from the
46
- # -- user hence we don't wrap inside output trapping executors.
47
- # --
48
- system "git push origin master"
49
-
50
- end
51
-
52
-
53
- # -- ------------------------------------------------- -- #
54
- # -- Return the branch name of a local git repository. -- #
55
- # -- ------------------------------------------------- -- #
56
- # -- Parameter -- #
57
- # -- path_to_dot_git : local path to the .git folder -- #
58
- # -- -- #
59
- # -- Dependencies and Assumptions -- #
60
- # -- git is installed on the machine -- #
61
- # -- ------------------------------------------------- -- #
62
- def self.wc_branch_name path_to_dot_git
63
-
64
- cmd = "git --git-dir=#{path_to_dot_git} branch";
65
- branch_names = %x[#{cmd}];
66
- branch_names.each_line do |line|
67
- return line[2, line.length].strip if line.start_with?('*')
68
- end
69
- raise ArgumentError.new "No branch name starts with asterix.\n#{cmd}\n#{branch_names}\n"
70
-
71
- end
72
-
73
-
74
- # -- ------------------------------------------------- -- #
75
- # -- Get the remote origin url of a git working copy. -- #
76
- # -- ------------------------------------------------- -- #
77
- # -- Parameter -- #
78
- # -- path_to_dot_git : local path to .git folder -- #
79
- # -- -- #
80
- # -- Dependencies and Assumptions -- #
81
- # -- git is installed on the machine -- #
82
- # -- working copy exists and has remote origin -- #
83
- # -- ------------------------------------------------- -- #
84
- def self.wc_origin_url path_to_dot_git
85
-
86
- cmd = "git --git-dir=#{path_to_dot_git} config --get remote.origin.url"
87
- url = %x[#{cmd}];
88
- raise ArgumentError.new "No remote origin url.\n#{cmd}\n" if url.nil?
89
-
90
- return url.strip
91
-
92
- end
93
-
94
-
95
- # -- -------------------------------------------------- -- #
96
- # -- Get the uncut revision of a git repo working copy. -- #
97
- # -- -------------------------------------------------- -- #
98
- # -- Parameter -- #
99
- # -- path_to_dot_git : local path to .git folder -- #
100
- # -- -- #
101
- # -- Dependencies and Assumptions -- #
102
- # -- git is installed on the machine -- #
103
- # -- working copy exists and has remote origin -- #
104
- # -- -------------------------------------------------- -- #
105
- def self.wc_revision_uncut path_to_dot_git
106
-
107
- log.info(ere) { "##### GitFlow path to dot git is => #{path_to_dot_git}" }
108
- repo_url = wc_origin_url path_to_dot_git
109
- log.info(ere) { "##### The GitFlow repo url is => #{repo_url}" }
110
-
111
- ## Bug HERE - On Ubuntu the branch name is like => (HEAD detached at 067f9a3)
112
- ## Bug HERE - This creates a failure of => sh: 1: Syntax error: "(" unexpected
113
- ## Bug HERE - The unexpected failure occurs in the ls-remote command below
114
- ## Bug HERE - So hardcoding this to "master" for now
115
- # branch_name = wc_branch_name path_to_dot_git
116
- branch_name = "master"
117
-
118
- log.info(ere) { "##### The GitFlow branch name is => #{branch_name}" }
119
- cmd = "git ls-remote #{repo_url} ls-remote -b #{branch_name}"
120
- log.info(ere) { "##### The GitFlow get dirty rev command is => #{cmd}" }
121
- dirty_revision = %x[#{cmd}];
122
- log.info(ere) { "##### The dirty revision is => #{dirty_revision}" }
123
- return dirty_revision.partition("refs/heads").first.strip;
124
-
125
- end
126
-
127
-
128
- # -- -------------------------------------------------- -- #
129
- # -- Get brief revision of repo from working copy path. -- #
130
- # -- -------------------------------------------------- -- #
131
- # -- Parameter -- #
132
- # -- path_to_dot_git : local path to .git folder -- #
133
- # -- -- #
134
- # -- Dependencies and Assumptions -- #
135
- # -- we return the first 7 revision chars -- #
136
- # -- git is installed on the machine -- #
137
- # -- working copy exists and has remote origin -- #
138
- # -- -------------------------------------------------- -- #
139
- def self.wc_revision path_to_dot_git
140
-
141
- log.info(ere) { "GitFlow path to dot git is => #{path_to_dot_git}" }
142
- Throw.if_not_exists path_to_dot_git
143
-
144
- uncut_revision = wc_revision_uncut path_to_dot_git
145
- log.info(ere) { "GitFlow uncut full revision is => #{uncut_revision}" }
146
-
147
- # -- --------------------------------------------------------------------- -- #
148
- # -- Gits [short revision] hash has 7 chars. Note 4 is the usable minimum. -- #
149
- # -- For usage in stamps where space comes at a premium - 6 chars will do. -- #
150
- # -- --------------------------------------------------------------------- -- #
151
- ref_length = 7
152
- return "r" + uncut_revision[0..(ref_length - 1)];
153
-
154
- end
155
-
156
-
157
- # -- -------------------------------------------------- -- #
158
- # -- Clone the branch of a local git repo working copy. -- #
159
- # -- -------------------------------------------------- -- #
160
- # -- Parameter -- #
161
- # -- src_gitpath : local path to .git folder -- #
162
- # -- new_wc_path : path to new non-existent dir -- #
163
- # -- -- #
164
- # -- Dependencies and Assumptions -- #
165
- # -- git is installed on the machine -- #
166
- # -- working copy exists and has remote origin -- #
167
- # -- -------------------------------------------------- -- #
168
- def self.do_clone_wc path_to_dot_git, path_to_new_dir
169
-
170
- # -- ----------------------------------------------------------- -- #
171
- # -- Why clone from a working copy (instead of a remote url). -- #
172
- # -- ----------------------------------------------------------- -- #
173
- # -- -- #
174
- # -- When actively [DEVELOPING] an eco plugin and you want to -- #
175
- # -- -- #
176
- # -- 1 - [test] the behaviour without a git commit/git push -- #
177
- # -- 2 - test whatever [branch] the working copy is now at -- #
178
- # -- -- #
179
- # -- This use case requires us to clone from a working copy. -- #
180
- # -- -- #
181
- # -- ----------------------------------------------------------- -- #
182
-
183
- ### Bug here - see getting branch name issue
184
- ### Bug here - see getting branch name issue
185
- ### Bug here - see getting branch name issue
186
- ### Bug here - see getting branch name issue
187
- ### branch_name = wc_branch_name path_to_dot_git
188
- branch_name = "master"
189
- ##### cmd = "git clone #{path_to_dot_git} -b #{branch_name} #{path_to_new_dir}"
190
- ##### cmd = "git clone #{path_to_dot_git} -b #{branch_name} #{path_to_new_dir}"
191
- ##### cmd = "git clone #{path_to_dot_git} -b #{branch_name} #{path_to_new_dir}"
192
- cmd = "git clone #{path_to_dot_git} #{path_to_new_dir}"
193
- clone_output = %x[#{cmd}];
194
-
195
- log.info(ere) { "[gitflow] cloning working copy" }
196
- log.info(ere) { "[gitflow] repo branch name : #{branch_name}" }
197
- log.info(ere) { "[gitflow] src dot git path : #{path_to_dot_git}" }
198
- log.info(ere) { "[gitflow] new wc dir path : #{path_to_new_dir}" }
199
- log.info(ere) { "[gitflow] git clone command : #{cmd}" }
200
- log.info(ere) { "[gitflow] git clone output : #{clone_output}" }
201
-
202
- end
203
-
204
-
205
- # --
206
- # -- Clone a remote repository at the specified [url] into
207
- # -- a [NON-EXISTENT] folder path.
208
- # --
209
- # -- ---------------------------------
210
- # -- What is a Non Existent Dir Path?
211
- # -- ---------------------------------
212
- # --
213
- # -- The parent directory of a non existent folder path
214
- # -- must [exist] whilst the full path itself does not.
215
- # -- The clone operation will create the final folder in
216
- # -- the path and then it [puts] the repository contents
217
- # -- within it.
218
- # --
219
- # -- -----------
220
- # -- Parameters
221
- # -- -----------
222
- # --
223
- # -- repo_url : url ends in dot git f-slash
224
- # -- clone_dir : path to new non-existent dir
225
- # --
226
- # -- -----------------------------
227
- # -- Dependencies and Assumptions
228
- # -- -----------------------------
229
- # --
230
- # -- git is installed on the machine
231
- # -- repo exists and is publicly readable
232
- # -- the master branch is he one to clone
233
- # -- the current Dir.pwd() is writeable
234
- # --
235
- def self.do_clone_repo repo_url, non_existent_path
236
-
237
- cmd = "git clone #{repo_url} #{non_existent_path}"
238
- clone_output = %x[#{cmd}];
239
-
240
- log.info(ere) { "[gitflow] cloning remote repository" }
241
- log.info(ere) { "[gitflow] git repository url : #{repo_url}" }
242
- log.info(ere) { "[gitflow] git clone dir path : #{nickname non_existent_path}" }
243
- log.info(ere) { "[gitflow] git clone command : #{cmd}" }
244
- log.info(ere) { "[gitflow] git clone output : #{clone_output}" }
245
-
246
- end
247
-
248
-
249
- # -- ----------------------------------------------------- -- #
250
- # -- Clone [many] git repositories given an array of urls -- #
251
- # -- along with a corresponding array of the working copy -- #
252
- # -- folder names and a [parental] base (offset) folder. -- #
253
- # -- ----------------------------------------------------- -- #
254
- # -- Parameter -- #
255
- # -- repo_urls : array of git repository urls -- #
256
- # -- base_names : array of cloned repo base names -- #
257
- # -- parent_dir : path to local [parent] folder -- #
258
- # -- -- #
259
- # -- Dependencies and Assumptions -- #
260
- # -- arrays have equiv corresponding entries -- #
261
- # -- parent dir is created if not exists -- #
262
- # -- repos exist and are publicly readable -- #
263
- # -- master branches are the ones to clone -- #
264
- # -- ----------------------------------------------------- -- #
265
- def self.do_clone_repos repo_urls, base_names, parent_dir
266
-
267
- Dir.mkdir parent_dir unless File.exists? parent_dir
268
- Throw.if_not_found parent_dir, "clone repos"
269
-
270
- repo_urls.each_with_index do | repo_url, repo_index |
271
-
272
- git_url = repo_url if repo_url.end_with? @@url_postfix
273
- git_url = "#{repo_url}#{@@url_postfix}" unless repo_url.end_with? @@url_postfix
274
-
275
- proj_folder = File.join parent_dir, base_names[repo_index]
276
-
277
- log.info(ere) { "[clone repos] proj [index] => #{repo_index}" }
278
- log.info(ere) { "[clone repos] repo url 1st => #{repo_url}" }
279
- log.info(ere) { "[clone repos] repo url 2nd => #{git_url}" }
280
- log.info(ere) { "[clone repos] project name => #{base_names[repo_index]}" }
281
- log.info(ere) { "[clone repos] project path => #{proj_folder}" }
282
-
283
- GitFlow.do_clone_repo git_url, proj_folder
284
-
285
- end
286
-
287
- end
288
-
289
-
290
- # -- ------------------------------------------------ -- #
291
- # -- Move assets from a git repo to a local zip file. -- #
292
- # -- ------------------------------------------------ -- #
293
- # -- -- #
294
- # -- Parameter -- #
295
- # -- repo_url : the url of the git repository -- #
296
- # -- path_offset : FWD-SLASH ENDED PATH in repo -- #
297
- # -- target_dir : the target folder for new zip -- #
298
- # -- zip_filename : extensionless name of the zip -- #
299
- # -- -- #
300
- # -- Return -- #
301
- # -- path to the zip file created in a tmp folder -- #
302
- # -- -- #
303
- # -- ------------------------------------------------ -- #
304
- # -- Dependencies and Assumptions -- #
305
- # -- ------------------------------------------------ -- #
306
- # -- -- #
307
- # -- END PATH OFFSET WITH A FORWARD SLASH -- #
308
- # -- IF NO OFFSET SEND "/" for path_offset -- #
309
- # -- git is installed on the machine -- #
310
- # -- the repo exists with path offset -- #
311
- # -- the master branch is archived -- #
312
- # -- name is unique as used to create a dir -- #
313
- # -- -- #
314
- # -- ------------------------------------------------ -- #
315
- def self.git2zip repo_url, path_offset, target_dir, zip_basename
316
-
317
- log.info(ere) { "[git2zip] ------------------------------------------- -- #" }
318
- log.info(ere) { "[git2zip] archiving repo assets at path offset -- #" }
319
- log.info(ere) { "[git2zip] ------------------------------------------- -- #" }
320
- log.info(ere) { "[git2zip] git repository url : #{repo_url}" }
321
- log.info(ere) { "[git2zip] slash tail dir offset : #{path_offset}" }
322
- log.info(ere) { "[git2zip] target zip directory : #{target_dir}" }
323
- log.info(ere) { "[git2zip] zip file [base] name : #{zip_basename}" }
324
-
325
- clone_dir = File.join Dir.tmpdir(), zip_basename
326
- do_clone_repo repo_url, clone_dir
327
- dot_git_path = File.join clone_dir, ".git"
328
- dst_zip_path = File.join target_dir, "#{zip_basename}.zip"
329
-
330
- the_offset = path_offset
331
- the_offset = "" if path_offset.length == 1
332
- cmd = "git --git-dir=#{dot_git_path} archive -o #{dst_zip_path} HEAD:#{the_offset}"
333
- clone_output = %x[#{cmd}];
334
-
335
- log.info(ere) { "[git2zip] tmp clone src folder : #{clone_dir}" }
336
- log.info(ere) { "[git2zip] cloned dot git path : #{dot_git_path}" }
337
- log.info(ere) { "[git2zip] target zip full path : #{dst_zip_path}" }
338
- log.info(ere) { "[git2zip] git archive command : #{cmd}" }
339
- log.info(ere) { "[git2zip] ------------------------------------------- -- #" }
340
- log.info(ere) { "#{clone_output}" }
341
- log.info(ere) { "[git2zip] ------------------------------------------- -- #" }
342
-
343
- return dst_zip_path
344
-
345
- end
346
-
347
-
348
- # -- ------------------------------------------------- -- #
349
- # -- Return an array of simple file names in the repo. -- #
350
- # -- ------------------------------------------------- -- #
351
- # -- Parameter -- #
352
- # -- repo_url : the url of the repository to read -- #
353
- # -- -- #
354
- # -- Dependencies and Assumptions -- #
355
- # -- we are not interested in folders -- #
356
- # -- trawl is recursive (infinite depth) -- #
357
- # -- git is installed on the machine -- #
358
- # -- ------------------------------------------------- -- #
359
- def self.file_names repo_url
360
-
361
- random_text = SecureRandom.urlsafe_base64(12).delete("-_").downcase
362
- cloned_name = "eco.repo.clone.#{random_text}"
363
- cloned_path = File.join Dir.tmpdir(), cloned_name
364
-
365
- do_clone_repo repo_url, cloned_path
366
- dot_git_path = File.join cloned_path, ".git"
367
-
368
- cmd = "git --git-dir=#{dot_git_path} ls-tree -r master --name-only"
369
- filename_lines = %x[#{cmd}];
370
- names_list = Array.new
371
- filename_lines.each_line do |line|
372
- names_list.push line.strip
373
- end
374
-
375
- log.info(ere) { "[git2files] ----------------------------------------------" }
376
- log.info(ere) { "[git2files] [#{names_list.length}] files in [#{repo_url}]" }
377
- log.info(ere) { "[git2files] ----------------------------------------------" }
378
- log.info(ere) { "[git2files] Random Text : #{random_text}" }
379
- log.info(ere) { "[git2files] Cloned Name : #{cloned_name}" }
380
- log.info(ere) { "[git2files] Cloned Path : #{cloned_path}" }
381
- log.info(ere) { "[git2files] Repo Folder : #{dot_git_path}" }
382
- log.info(ere) { "[git2files] Reading Cmd : #{cmd}" }
383
- log.info(ere) { "[git2files] ----------------------------------------------" }
384
- pp names_list
385
- log.info(ere) { "[git2files] ----------------------------------------------" }
386
-
387
- return names_list
388
-
389
- end
390
-
391
-
392
-
393
- end
394
-
395
-
396
- end
397
-
398
- end
399
-
data/lib/plugin/github.rb DELETED
@@ -1,53 +0,0 @@
1
- #!/usr/bin/ruby
2
-
3
- module SafeDb
4
-
5
- # This class knows how to talk to Github and callers can delegate common
6
- # github functionality like creating repositories, listing repositories,
7
- # downloading repositories and the like.
8
- #
9
- class Github
10
-
11
- # Initialize an instance of this safe database's master properties.
12
- def initialize()
13
-
14
-
15
-
16
-
17
- #
18
- #
19
- # Test the Github api using curl
20
- #
21
- #
22
- # curl -H "Authorization: token OAUTH-TOKEN" https://api.github.com
23
- #
24
- #
25
-
26
-
27
- @master = DataMap.new( Indices::MASTER_INDICES_FILEPATH )
28
- end
29
-
30
-
31
- # Get the coordinates (book, chapter and verse) of the verse that holds
32
- # the remote backend properties. An exception will be thrown if no backend
33
- # coordinates have been set.
34
- # @return [String] the backend coordinates to set
35
- def get_backend_coordinates()
36
- @master.use( Indices::REMOTE_MIRROR_SECTION_NAME )
37
- return @master.get( Indices::REMOTE_MIRROR_PAGE_NAME )
38
- end
39
-
40
-
41
- # Set the coordinates (book, chapter and verse) of the verse that holds
42
- # the remote backend properties.
43
- # @param backend_coordinates [String] the backend coordinates to set
44
- def set_backend_coordinates( backend_coordinates )
45
- @master.use( Indices::REMOTE_MIRROR_SECTION_NAME )
46
- @master.set( Indices::REMOTE_MIRROR_PAGE_NAME, backend_coordinates )
47
- end
48
-
49
-
50
- end
51
-
52
-
53
- end
@@ -1,27 +0,0 @@
1
- #!/usr/bin/ruby
2
- # coding: utf-8
3
-
4
- module SafeDb
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
- class Github
9
-
10
- # Initialize a Github repository given the parameter name.
11
- # the parameter JSON string.
12
- #
13
- # @param repository_name [String] name of the Github repository
14
- #
15
- def initialize( repository_name )
16
-
17
- data_db = DataStore.new()
18
- data_db.merge!( JSON.parse( db_json_string ) )
19
- return data_db
20
-
21
- end
22
-
23
-
24
- end
25
-
26
-
27
- end