dev_snap 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d3ae2f36b440a48ffd92edba27c74f0db21a135be6941cb2ab5fdeffdc7c746a
4
+ data.tar.gz: f40c68029e2ca16ebec71b6fb9988022c6aa5f91566bc1bc1a8f62fb9ae57cc9
5
+ SHA512:
6
+ metadata.gz: 428abe9df3c05efad935135553062d224103fbcdfb2fd6aa3e34523f2f49903308e55bcd58ef3da9fe24fe55ae7ebe9a409065451f6a409d6c4ae5c8f3fdef35
7
+ data.tar.gz: c068a9fc28d2d4199dcb282fe8f9f03c08fc1bb08da04f845585e8445cbb13e30d52d01b5fa480ead9b9489c4728de26562b2c2992991a3e144633dd15224610
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # DevSnap
2
+
3
+ TODO: Delete this and the text below, and describe your gem
4
+
5
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/dev_snap`. To experiment with that code, run `bin/console` for an interactive prompt.
6
+
7
+ ## Installation
8
+
9
+ TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
10
+
11
+ Install the gem and add to the application's Gemfile by executing:
12
+
13
+ $ bundle add UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
14
+
15
+ If bundler is not being used to manage dependencies, install the gem by executing:
16
+
17
+ $ gem install UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Development
24
+
25
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
26
+
27
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
28
+
29
+ ## Contributing
30
+
31
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/dev_snap.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
9
+ require 'release/gem'
data/exe/devsnap ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if ARGV.length == 0
4
+ STDERR.puts "devsnap <path>"
5
+ else
6
+ require_relative '../lib/dev_snap'
7
+
8
+ require 'tty/prompt'
9
+ require 'colorize'
10
+
11
+ pmt = TTY::Prompt.new
12
+ cm = DevSnap::Cli::CliManager.new(pmt)
13
+ begin
14
+ cm.parse_argv(ARGV)
15
+ rescue Exception => ex
16
+ STDERR.puts "\n Error >> #{ex.message}\n".red
17
+ STDERR.puts ex.backtrace.join("\n") if ENV['DEVSNAP_BACKTRACE'] == 'true'
18
+ end
19
+ end
@@ -0,0 +1,136 @@
1
+
2
+ require 'toolrack'
3
+
4
+ module DevSnap
5
+ module Cli
6
+
7
+ class CliManager
8
+ include TR::CondUtils
9
+ include TR::ArgUtils
10
+
11
+ callback :pre_processing do |a|
12
+ derive_action(a)
13
+ end
14
+
15
+ def initialize(pmt)
16
+ @pmt = pmt
17
+ end
18
+
19
+ def derive_action(a)
20
+
21
+ @pmt.puts "\n DevSnap version #{DevSnap::VERSION}".yellow
22
+ ops = a.first
23
+
24
+ case ops.downcase
25
+ when 'snap-root', 'root'
26
+ root = action_set_snap_root(a[1..-1])
27
+ @pmt.puts "\n Snap root is set at : #{root}\n".green
28
+
29
+ when 'add', 'a'
30
+ ws = action_add(a[1..-1])
31
+ @pmt.puts "\n Workspace '#{ws}' is added to monitoring list\n".green
32
+
33
+ when 'forget','ignore'
34
+ action_forget(a[1..-1])
35
+ @pmt.puts "\n Workspace '#{ws}' is removed from monitoring list\n".yellow
36
+
37
+ when 'list', 'l'
38
+ action_list
39
+
40
+ when 'run','r'
41
+ start, done, duration = action_run
42
+ @pmt.puts "Run starts on #{start} and ends on #{done}. Took #{duration} seconds"
43
+
44
+ else
45
+ logger.debug "Unknown action '#{ops.downcase}"
46
+ end
47
+
48
+ [true, []]
49
+
50
+ end
51
+
52
+
53
+ private
54
+ def logger
55
+ DevSnap.logger(:cli_mgr)
56
+ end
57
+
58
+ def action_run
59
+
60
+ start = Time.now
61
+ logger.debug "Run started on #{start}"
62
+ engine.run
63
+ done = Time.now
64
+ duration = done-start
65
+ logger.debug "Run completed on #{done} [#{duration} sec]"
66
+ [start, done, duration]
67
+
68
+ end
69
+
70
+ def action_set_snap_root(params)
71
+
72
+ fpath = params.first
73
+ raise Error, "Snap root is not given" if is_empty?(fpath)
74
+ fpath = File.expand_path(fpath)
75
+
76
+ engine.set_snap_root(fpath)
77
+ logger.debug "Snap root points to : #{fpath}"
78
+ fpath
79
+ end
80
+
81
+ def action_add(params)
82
+
83
+ fpath = params.first
84
+ raise Error, "Workspace to add not given" if is_empty?(fpath)
85
+ fpath = File.expand_path(fpath)
86
+
87
+ if not engine.is_monitoring?(fpath)
88
+ engine.monitor(fpath)
89
+ logger.debug "'#{fpath}' added to monitoring list"
90
+ else
91
+ logger.debug "'#{fpath}' already in monitoring list"
92
+ end
93
+
94
+ fpath
95
+
96
+ end
97
+
98
+ def action_forget(params)
99
+
100
+ fpath = params.first
101
+ raise Error, "Workspace to forget not given" if is_empty?(fpath)
102
+ fpath = File.expand_path(fpath)
103
+
104
+ if engine.is_monitoring?(fpath)
105
+ engine.ignore(fpath)
106
+ logger.debug "'#{fpath}' removed from monitoring list"
107
+ else
108
+ logger.debug "'#{fpath}' not in monitoring list. Forget/ignore request is skipped"
109
+ end
110
+
111
+ end
112
+
113
+ def action_list
114
+ list = engine.monitoring_paths
115
+ @pmt.puts "\n Monitoring List (#{list.length}) : ".blue
116
+ @pmt.puts " Snap Root : #{engine.snap_root}".blue
117
+ @pmt.puts
118
+ cnt = 1
119
+ engine.monitoring_paths.each do |pa|
120
+ @pmt.puts " #{cnt}. #{pa}".blue
121
+ cnt += 1
122
+ end
123
+ list
124
+ end
125
+
126
+ def engine
127
+
128
+ if @_eng.nil?
129
+ @_eng = DevSnap::Engine.new
130
+ end
131
+ @_eng
132
+
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,65 @@
1
+
2
+ require 'yaml'
3
+
4
+ module DevSnap
5
+
6
+ class Config
7
+ include Singleton
8
+ include TR::CondUtils
9
+
10
+ def set_snap_root(root)
11
+ _config[:snap_root] = root
12
+ write
13
+ end
14
+
15
+ def snap_root
16
+ _config[:snap_root]
17
+ end
18
+
19
+ def add_to_monitor(path)
20
+ if not_empty?(path)
21
+ _config[:path] = [] if is_empty?(_config[:path])
22
+ _config[:path] << path
23
+ write
24
+ end
25
+ end
26
+
27
+ def remove_path(path)
28
+ if not_empty?(path) and not_empty?(_config[:path])
29
+ _config[:path].delete(path)
30
+ write
31
+ end
32
+ end
33
+
34
+ def monitor_paths
35
+ _config[:path].nil? ? [] : _config[:path].clone.freeze
36
+ end
37
+
38
+ private
39
+ def _config
40
+ if @_config.nil?
41
+ if File.exist?(config_path)
42
+ #@_config = YAML.safe_load(File.read(config_path),[Symbol])
43
+ @_config = YAML.unsafe_load(File.read(config_path))
44
+ else
45
+ @_config = {}
46
+ end
47
+ end
48
+ @_config
49
+ end
50
+
51
+ def write
52
+ File.open(config_path,"w") do |f|
53
+ f.write YAML.dump(_config)
54
+ end
55
+ end
56
+
57
+ def config_path
58
+ pa = File.join(Dir.home,".devsnap","monitor_list.yml")
59
+ FileUtils.mkdir_p(File.dirname(pa)) if not File.exist?(pa)
60
+ pa
61
+ end
62
+
63
+ end
64
+
65
+ end
@@ -0,0 +1,60 @@
1
+
2
+ require_relative 'config'
3
+ require_relative 'snap_repos'
4
+ require_relative 'monitor_workspace'
5
+
6
+ module DevSnap
7
+ class Engine
8
+ include TR::CondUtils
9
+
10
+ def set_snap_root(path)
11
+ config.set_snap_root(path)
12
+ end
13
+
14
+ def snap_root
15
+ config.snap_root
16
+ end
17
+
18
+ def monitor(path)
19
+ config.add_to_monitor(path)
20
+ end
21
+
22
+ def is_monitoring?(path)
23
+ config.monitor_paths.include?(path)
24
+ end
25
+
26
+ def ignore(path)
27
+ config.remove_path(path)
28
+ end
29
+
30
+ def monitoring_paths
31
+ config.monitor_paths
32
+ end
33
+
34
+ def run
35
+
36
+ raise Error, "Snap root not given" if is_empty?(config.snap_root)
37
+
38
+ config.monitor_paths.each do |pa|
39
+ begin
40
+ sr = SnapRepos.new(config.snap_root, File.basename(pa))
41
+ backPath = sr.init
42
+ mw = MonitorWorkspace.new(pa, backPath)
43
+ mw.run
44
+ rescue Exception => ex
45
+ logger.error ex
46
+ end
47
+ end
48
+
49
+ end
50
+
51
+ private
52
+ def config
53
+ Config.instance
54
+ end
55
+
56
+ def logger
57
+ DevSnap.logger(:devsnap_eng)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,116 @@
1
+
2
+ require 'git_cli'
3
+ #require 'debug'
4
+
5
+ module DevSnap
6
+
7
+ #
8
+ # Strong assume it is git workspace
9
+ #
10
+ class MonitorWorkspace
11
+
12
+ VCSMarker = ".git"
13
+ DevSnapRepoName = "dev_snap_repos"
14
+
15
+ def initialize(root, backupReposPath)
16
+ @root = root
17
+ raise Error, "Root does not exist" if not File.exist?(@root)
18
+
19
+ @workspace = GitCli::Workspace.new(@root)
20
+ @backupReposPath = backupReposPath
21
+ end
22
+
23
+ def is_vcs_workspace?
24
+ @workspace.is_workspace?
25
+ end
26
+
27
+ def run
28
+
29
+ if is_vcs_workspace?
30
+
31
+ #binding.break
32
+
33
+ snapName = ".git_snap"
34
+ gitBackupName = ".git_prod"
35
+
36
+ prodGit = File.join(@root, VCSMarker)
37
+ prodGitBack = File.join(@root, gitBackupName)
38
+ snapGit = File.join(@root, snapName)
39
+
40
+ # Move .git folder to .git_prod...
41
+ logger.debug "Move #{prodGit} to #{prodGitBack}" if DevSnap.is_detail_debug?
42
+ FileUtils.mv(prodGit, prodGitBack)
43
+ # no more .git/...
44
+
45
+ begin
46
+ if not File.exist?(snapGit)
47
+ # init .git/
48
+ logger.debug "'#{snapGit}' doesn't exist. Init snap git"
49
+ @workspace.vcs.init(@root)
50
+ @workspace.add_remote(DevSnapRepoName, @backupReposPath)
51
+ @workspace.ignore(snapName, gitBackupName)
52
+ @workspace.commit("Adding backup git into ignore list")
53
+ else
54
+ # rename .git.snap/ to .git/
55
+ logger.debug "Rename #{snapGit} to #{prodGit}" if DevSnap.is_detail_debug?
56
+ FileUtils.mv(snapGit, prodGit)
57
+ end
58
+
59
+ # here, .git = snap git
60
+
61
+ if not @workspace.clean?
62
+ logger.debug "Workspace '#{@workspace.workspace_root}' has changes"
63
+ if DevSnap.is_detail_debug?
64
+ logger.debug "Workspace new files : #{@workspace.newFiles}"
65
+ logger.debug "Workspace modified files : #{@workspace.modFiles}"
66
+ logger.debug "Workspace staged files : #{@workspace.stgFiles}"
67
+ logger.debug "Workspace deleted files : #{@workspace.delFiles}"
68
+ logger.debug "Workspace conflicted files : #{@workspace.cftFiles}"
69
+ end
70
+
71
+ @workspace.add(".")
72
+ @workspace.commit("Added by DevSnap version #{DevSnap::VERSION} at #{Time.now}")
73
+
74
+ if not @workspace.remote_config.keys.include?("dev_snap_repos")
75
+ @workspace.add_remote(DevSnapRepoName, @backupReposPath)
76
+ end
77
+
78
+ @workspace.push_changes(DevSnapRepoName)
79
+
80
+ else
81
+ logger.debug "[Skipped] Workspace '#{@workspace.workspace_root}' is clean"
82
+ end
83
+
84
+ rescue Exception => ex
85
+ raise
86
+
87
+ ensure
88
+
89
+ # before begin block, .git/ already renamed to .git_prod
90
+ # If there is still .git/, then it must be the snap
91
+ if File.exist?(prodGit)
92
+ # rename .git to .git.snap.. no more .git
93
+ logger.debug "Rename #{prodGit} to #{snapGit}" if DevSnap.is_detail_debug?
94
+ FileUtils.mv(prodGit, snapGit)
95
+ end
96
+
97
+ # rename .git_prod to .git
98
+ logger.debug "Move #{prodGitBack} to #{prodGit}" if DevSnap.is_detail_debug?
99
+ FileUtils.mv(prodGitBack, prodGit)
100
+
101
+ end
102
+
103
+ else
104
+ logger.debug "Path '#{@root}' is not a VCS workspace"
105
+ end
106
+
107
+ end
108
+
109
+
110
+ private
111
+ def logger
112
+ DevSnap.logger(:mon_ws)
113
+ end
114
+
115
+ end
116
+ end
@@ -0,0 +1,35 @@
1
+
2
+
3
+ require 'git_cli'
4
+
5
+ module DevSnap
6
+
7
+ class SnapRepos
8
+ include TR::CondUtils
9
+
10
+ def initialize(root, name)
11
+ raise Error, "Snap repos root cannot be nil" if root.nil?
12
+ @root = root
13
+ FileUtils.mkdir_p(@root) if not File.exist?(@root)
14
+ @name = name
15
+ end
16
+
17
+ def init
18
+ target = File.join(@root, @name)
19
+ if not File.exist?(target)
20
+ logger.debug "Snap workspace '#{target}' does not exist. Creating new bare workspace"
21
+ GitCli::Vcs.new.init(target, true)
22
+ else
23
+ logger.debug "Snap workspace '#{target}' already exist."
24
+ end
25
+ target
26
+ end
27
+
28
+ private
29
+ def logger
30
+ DevSnap.logger(:snap_repos)
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DevSnap
4
+ VERSION = "0.1.7"
5
+ end
data/lib/dev_snap.rb ADDED
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'toolrack'
4
+ require 'teLogger'
5
+
6
+ require_relative "dev_snap/version"
7
+
8
+ require_relative 'dev_snap/engine'
9
+ require_relative 'dev_snap/cli_manager'
10
+
11
+ module DevSnap
12
+ include TR::CondUtils
13
+
14
+ class Error < StandardError; end
15
+ # Your code goes here...
16
+
17
+ def self.logger(tag = nil, &block)
18
+ if @_logger.nil?
19
+ @_logger = TeLogger::Tlogger.new('/home/chris/.devsnap/devsnap.log',5, 500*1024*1024)
20
+ @_logger.debug "DevSnap version #{DevSnap::VERSION} in action"
21
+ end
22
+
23
+ if block
24
+ if not_empty?(tag)
25
+ @_logger.with_tag(tag, &block)
26
+ else
27
+ @_logger.with_tag(@_logger.tag, &block)
28
+ end
29
+ else
30
+ if is_empty?(tag)
31
+ @_logger.tag = :devsnap
32
+ @_logger
33
+ else
34
+ # no block but tag is given? hmm
35
+ @_logger.tag = tag
36
+ @_logger
37
+ end
38
+ end
39
+
40
+ end # def logger
41
+
42
+
43
+ def self.is_detail_debug?
44
+ ENV["DevSnap_DetailDebug"] == "true"
45
+ end
46
+
47
+ end
data/sig/dev_snap.rbs ADDED
@@ -0,0 +1,4 @@
1
+ module DevSnap
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dev_snap
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.7
5
+ platform: ruby
6
+ authors:
7
+ - Chris
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-09-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: toolrack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.23'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.23'
27
+ - !ruby/object:Gem::Dependency
28
+ name: teLogger
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: git_cli
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.12'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.12'
55
+ - !ruby/object:Gem::Dependency
56
+ name: tty-prompt
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: colorize
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: debug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: release-gem
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: ''
112
+ email:
113
+ - chris@antrapol.com
114
+ executables:
115
+ - devsnap
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".rspec"
120
+ - README.md
121
+ - Rakefile
122
+ - exe/devsnap
123
+ - lib/dev_snap.rb
124
+ - lib/dev_snap/cli_manager.rb
125
+ - lib/dev_snap/config.rb
126
+ - lib/dev_snap/engine.rb
127
+ - lib/dev_snap/monitor_workspace.rb
128
+ - lib/dev_snap/snap_repos.rb
129
+ - lib/dev_snap/version.rb
130
+ - sig/dev_snap.rbs
131
+ homepage: ''
132
+ licenses: []
133
+ metadata: {}
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: 2.6.0
143
+ required_rubygems_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ requirements: []
149
+ rubygems_version: 3.4.6
150
+ signing_key:
151
+ specification_version: 4
152
+ summary: Development Snapshot - incremental backup utility
153
+ test_files: []