dsu 1.2.1 → 2.0.0.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +55 -21
- data/Gemfile.lock +7 -7
- data/README.md +28 -35
- data/bin/console +23 -1
- data/bin/dsu +3 -0
- data/bin/setup +14 -3
- data/exe/dsu +23 -1
- data/exe/dsu_migrate.rb +43 -0
- data/lib/core/ruby/color_theme_colors.rb +16 -0
- data/lib/core/ruby/color_theme_mode.rb +42 -0
- data/lib/core/ruby/not_today.rb +7 -0
- data/lib/core/ruby/wrap_and_join.rb +31 -0
- data/lib/dsu/base_cli.rb +19 -23
- data/lib/dsu/cli.rb +47 -37
- data/lib/dsu/command_services/add_entry_service.rb +10 -21
- data/lib/dsu/crud/json_file.rb +139 -0
- data/lib/dsu/crud/raw_json_file.rb +51 -0
- data/lib/dsu/env.rb +21 -0
- data/lib/dsu/migration/service.rb +196 -0
- data/lib/dsu/migration/version.rb +7 -0
- data/lib/dsu/models/color_theme.rb +270 -0
- data/lib/dsu/models/configuration.rb +160 -0
- data/lib/dsu/models/entry.rb +6 -2
- data/lib/dsu/models/entry_group.rb +143 -42
- data/lib/dsu/models/migration_version.rb +48 -0
- data/lib/dsu/presenters/base_presenter.rb +32 -0
- data/lib/dsu/presenters/color_theme_presenter.rb +50 -0
- data/lib/dsu/presenters/color_theme_show_presenter.rb +49 -0
- data/lib/dsu/presenters/configuration_presenter.rb +45 -0
- data/lib/dsu/presenters/entry_group_presenter.rb +35 -0
- data/lib/dsu/presenters/entry_presenter.rb +25 -0
- data/lib/dsu/services/color_theme/hydrator_service.rb +42 -0
- data/lib/dsu/services/configuration/hydrator_service.rb +42 -0
- data/lib/dsu/services/entry/hydrator_service.rb +33 -0
- data/lib/dsu/services/entry_group/editor_service.rb +107 -0
- data/lib/dsu/services/entry_group/hydrator_service.rb +37 -0
- data/lib/dsu/services/migration_version/hydrator_service.rb +36 -0
- data/lib/dsu/services/stderr_redirector_service.rb +27 -0
- data/lib/dsu/services/temp_file/reader_service.rb +33 -0
- data/lib/dsu/services/temp_file/writer_service.rb +35 -0
- data/lib/dsu/subcommands/base_subcommand.rb +14 -0
- data/lib/dsu/subcommands/config.rb +92 -32
- data/lib/dsu/subcommands/edit.rb +3 -3
- data/lib/dsu/subcommands/list.rb +70 -93
- data/lib/dsu/subcommands/theme.rb +159 -0
- data/lib/dsu/support/ask.rb +14 -19
- data/lib/dsu/support/color_themable.rb +34 -0
- data/lib/dsu/support/command_help_colorizeable.rb +27 -0
- data/lib/dsu/support/command_hookable.rb +60 -0
- data/lib/dsu/support/command_options/dsu_times.rb +32 -21
- data/lib/dsu/support/command_options/time.rb +7 -1
- data/lib/dsu/support/command_options/time_mneumonic.rb +7 -1
- data/lib/dsu/support/descriptable.rb +6 -4
- data/lib/dsu/support/entry_group_viewable.rb +28 -4
- data/lib/dsu/support/fileable.rb +94 -0
- data/lib/dsu/support/presentable.rb +11 -0
- data/lib/dsu/support/subcommand_help_colorizeable.rb +27 -0
- data/lib/dsu/support/time_comparable.rb +19 -0
- data/lib/dsu/support/time_formatable.rb +12 -0
- data/lib/dsu/support/times_sortable.rb +48 -14
- data/lib/dsu/support/utils.rb +11 -0
- data/lib/dsu/validators/color_theme_validator.rb +74 -0
- data/lib/dsu/validators/entries_validator.rb +4 -8
- data/lib/dsu/validators/version_validator.rb +29 -0
- data/lib/dsu/version.rb +2 -1
- data/lib/dsu/views/color_theme/index.rb +62 -0
- data/lib/dsu/views/color_theme/show.rb +106 -0
- data/lib/dsu/views/configuration/show.rb +41 -0
- data/lib/dsu/views/entry_group/edit.rb +3 -5
- data/lib/dsu/views/entry_group/shared/no_entries_to_display.rb +41 -0
- data/lib/dsu/views/entry_group/show.rb +16 -15
- data/lib/dsu/views/shared/error.rb +17 -0
- data/lib/dsu/views/shared/info.rb +17 -0
- data/lib/dsu/views/shared/message.rb +85 -0
- data/lib/dsu/views/shared/model_errors.rb +31 -0
- data/lib/dsu/views/shared/success.rb +17 -0
- data/lib/dsu/views/shared/warning.rb +17 -0
- data/lib/dsu.rb +22 -1
- data/lib/seed_data/themes/cherry.json +79 -0
- data/lib/seed_data/themes/default.json +79 -0
- data/lib/seed_data/themes/lemon.json +79 -0
- data/lib/seed_data/themes/matrix.json +79 -0
- data/lib/seed_data/themes/whiteout.json +79 -0
- metadata +70 -25
- data/lib/dsu/core/ruby/not_today.rb +0 -11
- data/lib/dsu/services/ai/tense_translator_service.rb +0 -63
- data/lib/dsu/services/configuration_loader_service.rb +0 -55
- data/lib/dsu/services/entry_group_deleter_service.rb +0 -31
- data/lib/dsu/services/entry_group_editor_service.rb +0 -96
- data/lib/dsu/services/entry_group_hydrator_service.rb +0 -43
- data/lib/dsu/services/entry_group_reader_service.rb +0 -36
- data/lib/dsu/services/entry_group_writer_service.rb +0 -46
- data/lib/dsu/services/entry_hydrator_service.rb +0 -35
- data/lib/dsu/services/temp_file_reader_service.rb +0 -31
- data/lib/dsu/services/temp_file_writer_service.rb +0 -33
- data/lib/dsu/support/colorable.rb +0 -14
- data/lib/dsu/support/configurable.rb +0 -15
- data/lib/dsu/support/configuration.rb +0 -112
- data/lib/dsu/support/entry_group_fileable.rb +0 -49
- data/lib/dsu/support/entry_group_loadable.rb +0 -49
- data/lib/dsu/support/folder_locations.rb +0 -21
- data/lib/dsu/support/say.rb +0 -40
- data/lib/dsu/views/edited_entries/shared/errors.rb +0 -39
- data/lib/dsu/views/shared/messages.rb +0 -56
data/lib/dsu/cli.rb
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'fileutils'
|
3
4
|
require 'time'
|
4
5
|
require_relative 'base_cli'
|
5
6
|
require_relative 'subcommands/config'
|
6
7
|
require_relative 'subcommands/edit'
|
7
8
|
require_relative 'subcommands/list'
|
9
|
+
require_relative 'subcommands/theme'
|
8
10
|
|
9
11
|
module Dsu
|
10
12
|
# The `dsu` command.
|
@@ -13,44 +15,41 @@ module Dsu
|
|
13
15
|
map %w[c -c] => :config
|
14
16
|
map %w[e -e] => :edit
|
15
17
|
map %w[l -l] => :list
|
18
|
+
map %w[t -t] => :theme
|
19
|
+
map %w[v -i] => :info
|
16
20
|
map %w[v -v] => :version
|
17
21
|
|
18
22
|
desc 'add, -a [OPTIONS] DESCRIPTION',
|
19
23
|
'Adds a DSU entry having DESCRIPTION to the date associated with the given OPTION'
|
20
24
|
long_desc <<-LONG_DESC
|
21
25
|
NAME
|
22
|
-
|
23
|
-
|
26
|
+
|
27
|
+
$ dsu add, -a [OPTIONS] DESCRIPTION -- will add a DSU entry having DESCRIPTION to the date associated with the given OPTION.
|
24
28
|
|
25
29
|
SYNOPSIS
|
26
|
-
|
27
|
-
|
30
|
+
|
31
|
+
$ dsu add, -a [-d DATE|-n|-t|-y] DESCRIPTION
|
28
32
|
|
29
33
|
OPTIONS:
|
30
|
-
|
34
|
+
|
31
35
|
-d DATE: Adds a DSU entry having DESCRIPTION to the DATE.
|
32
36
|
|
33
|
-
\x5
|
34
37
|
#{date_option_description}
|
35
38
|
|
36
|
-
\x5
|
37
39
|
-n: Adds a DSU entry having DESCRIPTION to today's date (`Time.now`).
|
38
40
|
|
39
|
-
\x5
|
40
41
|
-t: Adds a DSU entry having DESCRIPTION to tomorrow's date (`Time.new.tomorrow`).
|
41
42
|
|
42
|
-
\x5
|
43
43
|
-y: Adds a DSU entry having DESCRIPTION to yesterday's date (`Time.new.yesterday`).
|
44
44
|
|
45
45
|
DESCRIPTION:
|
46
|
-
|
46
|
+
|
47
47
|
Must be be between 2 and 256 characters (inclusive) in length.
|
48
48
|
LONG_DESC
|
49
49
|
option :date, type: :string, aliases: '-d'
|
50
50
|
option :tomorrow, type: :boolean, aliases: '-t'
|
51
51
|
option :yesterday, type: :boolean, aliases: '-y'
|
52
52
|
option :today, type: :boolean, aliases: '-n', default: true
|
53
|
-
|
54
53
|
def add(description)
|
55
54
|
time = if options[:date].present?
|
56
55
|
Time.parse(options[:date])
|
@@ -66,30 +65,6 @@ module Dsu
|
|
66
65
|
view_entry_group(time: time)
|
67
66
|
end
|
68
67
|
|
69
|
-
# def add(description)
|
70
|
-
# times = if options[:date].present?
|
71
|
-
# time = Time.parse(options[:date])
|
72
|
-
# [time, time.yesterday]
|
73
|
-
# else
|
74
|
-
# time = Time.now
|
75
|
-
# if options[:tomorrow].present?
|
76
|
-
# [time.tomorrow, time.tomorrow.yesterday]
|
77
|
-
# elsif options[:yesterday].present?
|
78
|
-
# [time.yesterday, time.yesterday.yesterday]
|
79
|
-
# elsif options[:today].present?
|
80
|
-
# [time, time.yesterday]
|
81
|
-
# end
|
82
|
-
# end
|
83
|
-
# entry = Models::Entry.new(description: description)
|
84
|
-
# # NOTE: We need to add the Entry to the date that is the furthest in the future
|
85
|
-
# # (time.max) because this is the DSU entry that the user specified.
|
86
|
-
# CommandServices::AddEntryService.new(entry: entry, time: times.max).call
|
87
|
-
# sorted_dsu_times_for(times: times).each do |t|
|
88
|
-
# view_entry_group(time: t)
|
89
|
-
# puts
|
90
|
-
# end
|
91
|
-
# end
|
92
|
-
|
93
68
|
desc 'list, -l SUBCOMMAND',
|
94
69
|
'Displays DSU entries for the given SUBCOMMAND'
|
95
70
|
subcommand :list, Subcommands::List
|
@@ -102,10 +77,45 @@ module Dsu
|
|
102
77
|
'Edit DSU entries for the given SUBCOMMAND'
|
103
78
|
subcommand :edit, Subcommands::Edit
|
104
79
|
|
80
|
+
desc 'theme, -t SUBCOMMAND',
|
81
|
+
'Manage DSU themes'
|
82
|
+
subcommand :theme, Subcommands::Theme
|
83
|
+
|
84
|
+
desc 'info, -i',
|
85
|
+
'Displays information about this dsu release'
|
86
|
+
def info
|
87
|
+
configuration_version = Models::Configuration::VERSION
|
88
|
+
entry_group_version = Models::EntryGroup::VERSION
|
89
|
+
color_theme_version = Models::ColorTheme::VERSION
|
90
|
+
info = <<~INFO
|
91
|
+
Dsu version: #{dsu_version}
|
92
|
+
Configuration version: #{configuration_version}
|
93
|
+
Entry group version: #{entry_group_version}
|
94
|
+
Color theme version: #{color_theme_version}
|
95
|
+
|
96
|
+
Config path: #{Support::Fileable.config_path}
|
97
|
+
Root folder: #{Support::Fileable.root_folder}
|
98
|
+
Entries folder: #{Support::Fileable.entries_folder}
|
99
|
+
Themes folder: #{Support::Fileable.themes_folder}
|
100
|
+
Gem folder: #{Support::Fileable.gem_dir}
|
101
|
+
Temp folder: #{Support::Fileable.temp_folder}
|
102
|
+
|
103
|
+
Migration version folder: #{Support::Fileable.migration_version_folder}
|
104
|
+
Migration file path: #{Support::Fileable.migration_version_path}
|
105
|
+
INFO
|
106
|
+
puts apply_theme(info, theme_color: color_theme.body)
|
107
|
+
end
|
108
|
+
|
105
109
|
desc 'version, -v',
|
106
|
-
'Displays this gem
|
110
|
+
'Displays the version for this gem'
|
107
111
|
def version
|
108
|
-
|
112
|
+
puts apply_theme(dsu_version, theme_color: color_theme.body)
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def dsu_version
|
118
|
+
"v#{VERSION}"
|
109
119
|
end
|
110
120
|
end
|
111
121
|
end
|
@@ -1,24 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../models/entry'
|
4
|
-
require_relative '../
|
5
|
-
require_relative '../support/colorable'
|
4
|
+
require_relative '../support/color_themable'
|
6
5
|
require_relative '../support/descriptable'
|
7
|
-
require_relative '../support/
|
8
|
-
require_relative '../
|
9
|
-
require_relative '../support/say'
|
10
|
-
require_relative '../views/shared/messages'
|
6
|
+
require_relative '../support/fileable'
|
7
|
+
require_relative '../views/shared/error'
|
11
8
|
|
12
9
|
module Dsu
|
13
10
|
module CommandServices
|
14
11
|
# This class adds (does NOT update) an entry to an entry group by
|
15
12
|
# writing it to the appropriate entry group json file.
|
16
13
|
class AddEntryService
|
17
|
-
include Support::
|
14
|
+
include Support::ColorThemable
|
18
15
|
include Support::Descriptable
|
19
|
-
include Support::
|
20
|
-
include Support::FolderLocations
|
21
|
-
include Support::Say
|
16
|
+
include Support::Fileable
|
22
17
|
|
23
18
|
attr_reader :entry, :entry_group, :time
|
24
19
|
|
@@ -34,28 +29,22 @@ module Dsu
|
|
34
29
|
|
35
30
|
@entry = entry
|
36
31
|
@time = time
|
37
|
-
@entry_group = Models::EntryGroup.
|
32
|
+
@entry_group = Models::EntryGroup.find_or_initialize(time: time)
|
38
33
|
end
|
39
34
|
|
40
35
|
def call
|
41
36
|
entry.validate!
|
42
|
-
|
37
|
+
entry_group.entries << entry
|
38
|
+
entry_group.save!
|
43
39
|
entry
|
44
40
|
rescue ActiveModel::ValidationError => e
|
45
|
-
header = 'An error was encountered; the entry could not be added
|
46
|
-
Views::Shared::
|
41
|
+
header = 'An error was encountered; the entry could not be added:'
|
42
|
+
Views::Shared::Error.new(messages: e.message, header: header).render
|
47
43
|
end
|
48
44
|
|
49
45
|
private
|
50
46
|
|
51
47
|
attr_writer :entry, :entry_group, :time
|
52
|
-
|
53
|
-
def save_entry_group!
|
54
|
-
entry_group.entries << entry
|
55
|
-
entry_group.validate!
|
56
|
-
|
57
|
-
Services::EntryGroupWriterService.new(entry_group: entry_group).call
|
58
|
-
end
|
59
48
|
end
|
60
49
|
end
|
61
50
|
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_model'
|
4
|
+
require 'json'
|
5
|
+
require_relative 'raw_json_file'
|
6
|
+
|
7
|
+
module Dsu
|
8
|
+
module Crud
|
9
|
+
class JsonFile
|
10
|
+
include ActiveModel::Model
|
11
|
+
|
12
|
+
attr_reader :file_path
|
13
|
+
|
14
|
+
def initialize(file_path)
|
15
|
+
@file_path = file_path
|
16
|
+
end
|
17
|
+
|
18
|
+
def delete
|
19
|
+
self.class.delete(file_path: file_path)
|
20
|
+
end
|
21
|
+
|
22
|
+
def delete!
|
23
|
+
self.class.delete!(file_path: file_path)
|
24
|
+
end
|
25
|
+
|
26
|
+
def exist?
|
27
|
+
self.class.exist?(file_path: file_path)
|
28
|
+
end
|
29
|
+
|
30
|
+
def persisted?
|
31
|
+
exist?
|
32
|
+
end
|
33
|
+
|
34
|
+
# Override this method to reload data from the file
|
35
|
+
def reload
|
36
|
+
@version = read_version
|
37
|
+
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_h
|
42
|
+
raise NotImplementedError, 'You must implement this method in a your subclass'
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_model
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
def version
|
50
|
+
@version ||= read_version
|
51
|
+
end
|
52
|
+
|
53
|
+
def write
|
54
|
+
return false unless valid?
|
55
|
+
|
56
|
+
self.class.write(file_data: to_h, file_path: file_path)
|
57
|
+
true
|
58
|
+
end
|
59
|
+
|
60
|
+
def write!
|
61
|
+
validate!
|
62
|
+
|
63
|
+
self.class.write(file_data: to_h, file_path: file_path)
|
64
|
+
end
|
65
|
+
|
66
|
+
alias save write
|
67
|
+
alias save! write!
|
68
|
+
|
69
|
+
class << self
|
70
|
+
def exist?(file_path:)
|
71
|
+
RawJsonFile.exist?(file_path: file_path)
|
72
|
+
end
|
73
|
+
|
74
|
+
def delete(file_path:)
|
75
|
+
RawJsonFile.delete(file_path: file_path)
|
76
|
+
end
|
77
|
+
|
78
|
+
def delete!(file_path:)
|
79
|
+
RawJsonFile.delete!(file_path: file_path)
|
80
|
+
end
|
81
|
+
|
82
|
+
def parse(json)
|
83
|
+
return if json.nil?
|
84
|
+
|
85
|
+
JSON.parse(json, symbolize_names: true)
|
86
|
+
end
|
87
|
+
|
88
|
+
def read(file_path:)
|
89
|
+
hash = parse(RawJsonFile.read(file_path: file_path))
|
90
|
+
return yield hash if hash && block_given?
|
91
|
+
|
92
|
+
hash
|
93
|
+
end
|
94
|
+
|
95
|
+
def read!(file_path:)
|
96
|
+
hash = parse(RawJsonFile.read!(file_path: file_path))
|
97
|
+
return yield hash if hash && block_given?
|
98
|
+
|
99
|
+
hash
|
100
|
+
end
|
101
|
+
|
102
|
+
def write(file_data:, file_path:)
|
103
|
+
Crud::RawJsonFile.write(file_data: file_data, file_path: file_path)
|
104
|
+
end
|
105
|
+
|
106
|
+
def write!(file_data:, file_path:)
|
107
|
+
write(file_data: file_data, file_path: file_path)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
def read
|
114
|
+
hash = self.class.parse(RawJsonFile.read(file_path: file_path))
|
115
|
+
return yield hash if block_given?
|
116
|
+
|
117
|
+
hash
|
118
|
+
end
|
119
|
+
|
120
|
+
def read!
|
121
|
+
hash = self.class.parse(RawJsonFile.read!(file_path: file_path))
|
122
|
+
return yield hash if hash && block_given?
|
123
|
+
|
124
|
+
hash
|
125
|
+
end
|
126
|
+
|
127
|
+
def read_version
|
128
|
+
return 0 unless exist?
|
129
|
+
|
130
|
+
hash = read
|
131
|
+
return 0 if hash.nil?
|
132
|
+
|
133
|
+
hash.fetch(:version, 0).to_i
|
134
|
+
end
|
135
|
+
|
136
|
+
attr_writer :file_path, :version
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module Dsu
|
6
|
+
module Crud
|
7
|
+
module RawJsonFile
|
8
|
+
class << self
|
9
|
+
def delete(file_path:)
|
10
|
+
return false unless exist?(file_path: file_path)
|
11
|
+
|
12
|
+
File.delete(file_path)
|
13
|
+
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
def delete!(file_path:)
|
18
|
+
raise file_does_not_exist_message(file_path: file_path) unless delete(file_path: file_path)
|
19
|
+
end
|
20
|
+
|
21
|
+
def exist?(file_path:)
|
22
|
+
File.exist?(file_path)
|
23
|
+
end
|
24
|
+
|
25
|
+
def read(file_path:)
|
26
|
+
File.read(file_path) if exist?(file_path: file_path)
|
27
|
+
end
|
28
|
+
|
29
|
+
def read!(file_path:)
|
30
|
+
raise file_does_not_exist_message(file_path: file_path) unless exist?(file_path: file_path)
|
31
|
+
|
32
|
+
read(file_path: file_path)
|
33
|
+
end
|
34
|
+
|
35
|
+
def write(file_data:, file_path:)
|
36
|
+
raise ArgumentError, 'file_data is nil' if file_data.nil?
|
37
|
+
raise ArgumentError, "file_data is the wrong object type:\"#{file_data}\"" unless file_data.is_a?(Hash)
|
38
|
+
|
39
|
+
file_data = JSON.pretty_generate(file_data)
|
40
|
+
File.write(file_path, file_data)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def file_does_not_exist_message(file_path:)
|
46
|
+
"File \"#{file_path}\" does not exist"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/dsu/env.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dsu
|
4
|
+
class << self
|
5
|
+
def env
|
6
|
+
@env ||= Struct.new(:env) do
|
7
|
+
def test?
|
8
|
+
env.fetch('DSU_ENV', nil) == 'test'
|
9
|
+
end
|
10
|
+
|
11
|
+
def development?
|
12
|
+
env.fetch('DSU_ENV', nil) == 'development'
|
13
|
+
end
|
14
|
+
|
15
|
+
def production?
|
16
|
+
env.fetch('DSU_ENV', 'production') == 'production'
|
17
|
+
end
|
18
|
+
end.new(ENV)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'json'
|
5
|
+
require_relative '../migration/version'
|
6
|
+
require_relative '../models/configuration'
|
7
|
+
require_relative '../models/migration_version'
|
8
|
+
require_relative '../support/fileable'
|
9
|
+
|
10
|
+
module Dsu
|
11
|
+
module Migration
|
12
|
+
MIGRATION_VERSION_REGEX = /(\A\d+)/
|
13
|
+
|
14
|
+
class Service
|
15
|
+
include Support::Fileable
|
16
|
+
|
17
|
+
def initialize(options: {})
|
18
|
+
@options = options || {}
|
19
|
+
@migration_version = Models::MigrationVersion.new(options: options)
|
20
|
+
@start_migration_version = @migration_version.version
|
21
|
+
end
|
22
|
+
|
23
|
+
def call
|
24
|
+
unless self.class.run_migrations?
|
25
|
+
puts 'Nothing to do.'
|
26
|
+
return
|
27
|
+
end
|
28
|
+
|
29
|
+
run_migrations!
|
30
|
+
end
|
31
|
+
|
32
|
+
class << self
|
33
|
+
def run_migrations?
|
34
|
+
Models::MigrationVersion.new.version < Dsu::Migration::VERSION
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
attr_reader :migration_version, :options, :start_migration_version
|
41
|
+
|
42
|
+
def run_migrations!
|
43
|
+
puts "dsu version: #{Dsu::VERSION}"
|
44
|
+
puts
|
45
|
+
|
46
|
+
puts 'Running migrations...'
|
47
|
+
puts
|
48
|
+
|
49
|
+
puts "Current migration version: #{start_migration_version}"
|
50
|
+
puts "Migrating to version: #{Dsu::Migration::VERSION}"
|
51
|
+
puts
|
52
|
+
|
53
|
+
backup!
|
54
|
+
cleanup!
|
55
|
+
migrate!
|
56
|
+
|
57
|
+
new_migration_version = Models::MigrationVersion.new(version: Dsu::Migration::VERSION).tap(&:save!).version
|
58
|
+
|
59
|
+
puts "Migration version after migration is: #{new_migration_version}"
|
60
|
+
puts 'Migration completed successfully.'
|
61
|
+
rescue StandardError => e
|
62
|
+
warn "Migration completed with errors: #{e.message}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def backup!
|
66
|
+
backup_config!
|
67
|
+
puts
|
68
|
+
|
69
|
+
backup_entry_groups!
|
70
|
+
puts
|
71
|
+
|
72
|
+
backup_themes!
|
73
|
+
puts
|
74
|
+
end
|
75
|
+
|
76
|
+
def backup_config!
|
77
|
+
puts 'Backing up config...'
|
78
|
+
if File.exist?(config_path)
|
79
|
+
backup_path = File.join(current_backup_folder, config_file_name)
|
80
|
+
puts "Backing up #{config_path} to #{backup_path}..."
|
81
|
+
FileUtils.cp(config_path, backup_path)
|
82
|
+
else
|
83
|
+
puts 'No config to backup.'
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def backup_entry_groups!
|
88
|
+
puts 'Backing up entry groups...'
|
89
|
+
if Dir.exist?(entries_folder)
|
90
|
+
backup_folder = File.join(current_backup_folder, File.basename(entries_folder))
|
91
|
+
puts "Backing up #{entries_folder} to #{backup_folder}..."
|
92
|
+
FileUtils.mkdir_p(backup_folder)
|
93
|
+
FileUtils.cp_r("#{entries_folder}/.", backup_folder)
|
94
|
+
else
|
95
|
+
puts 'No entries to backup.'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def backup_themes!
|
100
|
+
puts 'Backing up themes...'
|
101
|
+
if Dir.exist?(themes_folder)
|
102
|
+
backup_folder = File.join(current_backup_folder, File.basename(themes_folder))
|
103
|
+
puts "Backing up #{themes_folder} to #{backup_folder}..."
|
104
|
+
FileUtils.mkdir_p(backup_folder)
|
105
|
+
FileUtils.cp_r("#{themes_folder}/.", backup_folder)
|
106
|
+
else
|
107
|
+
puts 'No entries to backup.'
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def before_migration_version
|
112
|
+
@before_migration_version ||= migration_version_instance.version
|
113
|
+
end
|
114
|
+
|
115
|
+
def cleanup!
|
116
|
+
puts 'Cleaning up old config file...'
|
117
|
+
File.delete(config_path) if File.file?(config_path)
|
118
|
+
puts 'Done.'
|
119
|
+
puts
|
120
|
+
|
121
|
+
puts 'Cleaning up old entries...'
|
122
|
+
entry_files = Dir.glob(File.join(entries_folder, '*'))
|
123
|
+
entry_files.each do |entry_file|
|
124
|
+
File.delete(entry_file) if File.file?(entry_file)
|
125
|
+
end
|
126
|
+
puts 'Done.'
|
127
|
+
puts
|
128
|
+
|
129
|
+
puts 'Cleaning up old themes...'
|
130
|
+
theme_files = Dir.glob(File.join(themes_folder, '*'))
|
131
|
+
theme_files.each do |theme_file|
|
132
|
+
File.delete(theme_file) if File.file?(theme_file)
|
133
|
+
end
|
134
|
+
puts 'Done.'
|
135
|
+
puts
|
136
|
+
end
|
137
|
+
|
138
|
+
def create_backup_folder!
|
139
|
+
FileUtils.mkdir_p(backup_folder(version: current_migration_version))
|
140
|
+
end
|
141
|
+
|
142
|
+
def current_backup_folder
|
143
|
+
@current_backup_folder ||= begin
|
144
|
+
create_backup_folder!
|
145
|
+
backup_folder(version: current_migration_version)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def current_migration_version
|
150
|
+
migration_version_instance.version
|
151
|
+
end
|
152
|
+
|
153
|
+
# Migrate
|
154
|
+
|
155
|
+
def migrate!
|
156
|
+
FileUtils.mkdir_p(dsu_folder)
|
157
|
+
FileUtils.mkdir_p(themes_folder)
|
158
|
+
FileUtils.mkdir_p(entries_folder)
|
159
|
+
|
160
|
+
migrate_themes!
|
161
|
+
migrate_config!
|
162
|
+
migrate_entry_groups!
|
163
|
+
end
|
164
|
+
|
165
|
+
def migrate_config!
|
166
|
+
puts 'Migrating config...'
|
167
|
+
Models::Configuration.new.save!
|
168
|
+
puts 'Done.'
|
169
|
+
end
|
170
|
+
|
171
|
+
def migrate_entry_groups!
|
172
|
+
puts 'Migrating entry groups...'
|
173
|
+
# source_folder = File.join(seed_data_folder, 'entries')
|
174
|
+
# puts "Copying entries from #{source_folder} to #{entries_folder}..."
|
175
|
+
# FileUtils.cp_r("#{source_folder}/.", entries_folder)
|
176
|
+
# puts 'Done.'
|
177
|
+
description = "Migrated DSU to version #{Dsu::Migration::VERSION}"
|
178
|
+
entry = Models::Entry.new(description: description)
|
179
|
+
Models::EntryGroup.new(time: Time.now, entries: [entry]).save!
|
180
|
+
puts 'Done.'
|
181
|
+
end
|
182
|
+
|
183
|
+
def migrate_themes!
|
184
|
+
puts 'Migrating themes...'
|
185
|
+
source_folder = File.join(seed_data_folder, 'themes')
|
186
|
+
puts "Copying themes from #{source_folder} to #{themes_folder}..."
|
187
|
+
FileUtils.cp_r("#{source_folder}/.", themes_folder)
|
188
|
+
puts 'Done.'
|
189
|
+
end
|
190
|
+
|
191
|
+
def migration_version_instance
|
192
|
+
@migration_version_instance ||= Models::MigrationVersion.new
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|