rails-dev-tools 1.1.2
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +109 -0
- data/Rakefile +29 -0
- data/app/assets/config/dev_manifest.js +0 -0
- data/bin/dev +6 -0
- data/config/routes.rb +2 -0
- data/lib/dev.rb +12 -0
- data/lib/dev/engine.rb +4 -0
- data/lib/dev/executable.rb +205 -0
- data/lib/dev/executables/commands/feature.rb +111 -0
- data/lib/dev/executables/commands/hotfix.rb +121 -0
- data/lib/dev/executables/commands/pull.rb +51 -0
- data/lib/dev/executables/commands/push.rb +59 -0
- data/lib/dev/executables/commands/release.rb +133 -0
- data/lib/dev/executables/commands/status.rb +39 -0
- data/lib/dev/executables/commands/test.rb +49 -0
- data/lib/dev/executables/commands/version.rb +21 -0
- data/lib/dev/project.rb +131 -0
- data/lib/dev/rainbow.rb +29 -0
- data/lib/dev/version.rb +3 -0
- data/lib/generators/dev/config_generator.rb +18 -0
- data/lib/generators/templates/dev.yml.erb +44 -0
- data/lib/tasks/dev_tasks.rake +4 -0
- metadata +140 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 8521d4f1cf1ae2731589db49050da30beb1b71b857cb47ae132f7c62be024af5
|
4
|
+
data.tar.gz: e6f4994b5adcd9ab50e043b2c348b58af9ae5ba837e78bff2503454d7fe40a0f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: aae21b0b0c2df5aa30e51e3beadeb801a233d3311ea36806b4dedc8680131f28a19872a01d2fe1b976b32242564ee9a52d4bccad059983cd08642861cdda8a16
|
7
|
+
data.tar.gz: 550f75d96be2edb8003d97ad4fec13a392e09e32e6ca1e5caccb377e393f78480fc09ca7704cda0b0e014ad3eba917a04e23847c439926fdecd3c1995245a8d8
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2018 Francesco Ballardin
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
# Dev
|
2
|
+
This gem installs an executable command named `dev` which aims to help you develop and maintain Ruby or Ruby on Rails projects.
|
3
|
+
|
4
|
+
This gem takes inspiration from the Git Workflow published on [this page](https://nvie.com/posts/a-successful-git-branching-model/).
|
5
|
+
|
6
|
+
This gem can be used with mini Ruby projects composed of just one directory and a few files and at the same time with big Rails projects with many main apps and engines.
|
7
|
+
|
8
|
+
To work with big project, it is assumed that you organized your folders as follows:
|
9
|
+
|
10
|
+
```bash
|
11
|
+
/path/to/project/ # Main project directory
|
12
|
+
/path/to/project/main_apps # Main apps directory
|
13
|
+
/path/to/project/main_apps/app1 # Main app 1
|
14
|
+
/path/to/project/main_apps/app2 # Main app 2
|
15
|
+
...
|
16
|
+
/path/to/project/engines # Engines directory
|
17
|
+
/path/to/project/engines/engine1 # Engine 1
|
18
|
+
/path/to/project/engines/engine2 # Engine 2
|
19
|
+
...
|
20
|
+
```
|
21
|
+
|
22
|
+
## Installation
|
23
|
+
Install with:
|
24
|
+
```bash
|
25
|
+
$ gem install rails-dev-tools
|
26
|
+
```
|
27
|
+
|
28
|
+
This will install an executable command named `dev`.
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
From the shell run:
|
32
|
+
```
|
33
|
+
$ dev help
|
34
|
+
```
|
35
|
+
|
36
|
+
To list all the available commands.
|
37
|
+
|
38
|
+
## Commands
|
39
|
+
|
40
|
+
Usual git commands are `pull` and `push`. If you have a big project, this helps you pulling and pushing without moving from the current directory.
|
41
|
+
|
42
|
+
### Pull
|
43
|
+
|
44
|
+
To pull data for a specific main app or engine:
|
45
|
+
|
46
|
+
```bash
|
47
|
+
dev pull app1
|
48
|
+
dev pull engine2
|
49
|
+
```
|
50
|
+
|
51
|
+
To pull data for all main apps and engines:
|
52
|
+
```
|
53
|
+
dev pull
|
54
|
+
```
|
55
|
+
|
56
|
+
### Push
|
57
|
+
|
58
|
+
To push data for a specific main app or engine:
|
59
|
+
|
60
|
+
```bash
|
61
|
+
dev push app1 "commit message"
|
62
|
+
dev push engine2 "commit message"
|
63
|
+
```
|
64
|
+
|
65
|
+
### Feature
|
66
|
+
|
67
|
+
If you want to start developing a new feature:
|
68
|
+
```bash
|
69
|
+
dev feature open my-new-feat
|
70
|
+
```
|
71
|
+
|
72
|
+
You will be placed on a new branch called `feature/my-new-feat`. Do all your work and then push it. After that, you can close your feature with:
|
73
|
+
```bash
|
74
|
+
dev feature close my-new-feat
|
75
|
+
```
|
76
|
+
|
77
|
+
This will merge the feature branch on the `develop` branch.
|
78
|
+
|
79
|
+
### Release
|
80
|
+
|
81
|
+
When all your work into the develop branch is ready to become a new release, run:
|
82
|
+
|
83
|
+
```bash
|
84
|
+
dev release open 0.2.0
|
85
|
+
```
|
86
|
+
|
87
|
+
You will be placed on a new branch called `release/0.2.0`. You can work on this branch until it becomes stable and passes all tests. At this point commit and push your work and then run:
|
88
|
+
```
|
89
|
+
dev release close 0.2.0
|
90
|
+
```
|
91
|
+
|
92
|
+
This will merge the release branch on the `master` branch.
|
93
|
+
|
94
|
+
### Hotfix
|
95
|
+
|
96
|
+
If you need to quickly fix a bug that accidentally made it to production, run:
|
97
|
+
```bash
|
98
|
+
dev hotfix open 0.2.1
|
99
|
+
```
|
100
|
+
|
101
|
+
You will be placed on a new branch called `hotfix/0.2.1`. While on this branch, write only code that fixes the bug(s) found. Do not start new features or continue developing existing ones. When you have fixed the bug run:
|
102
|
+
```bash
|
103
|
+
dev hotfix close 0.2.1
|
104
|
+
```
|
105
|
+
|
106
|
+
This will merge the hotfix branch on the `master` branch and on the `develop` branch.
|
107
|
+
|
108
|
+
## License
|
109
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Dev'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
load 'rails/tasks/statistics.rake'
|
18
|
+
|
19
|
+
require 'bundler/gem_tasks'
|
20
|
+
|
21
|
+
require 'rake/testtask'
|
22
|
+
|
23
|
+
Rake::TestTask.new(:test) do |t|
|
24
|
+
t.libs << 'test'
|
25
|
+
t.pattern = 'test/**/*_test.rb'
|
26
|
+
t.verbose = false
|
27
|
+
end
|
28
|
+
|
29
|
+
task default: :test
|
File without changes
|
data/bin/dev
ADDED
data/config/routes.rb
ADDED
data/lib/dev.rb
ADDED
data/lib/dev/engine.rb
ADDED
@@ -0,0 +1,205 @@
|
|
1
|
+
require 'open3'
|
2
|
+
require 'dev/project'
|
3
|
+
require 'dev/executables/commands/version'
|
4
|
+
require 'dev/executables/commands/status'
|
5
|
+
require 'dev/executables/commands/feature'
|
6
|
+
require 'dev/executables/commands/hotfix'
|
7
|
+
require 'dev/executables/commands/release'
|
8
|
+
require 'dev/executables/commands/pull'
|
9
|
+
require 'dev/executables/commands/push'
|
10
|
+
require 'dev/executables/commands/test'
|
11
|
+
|
12
|
+
module Dev
|
13
|
+
|
14
|
+
##
|
15
|
+
# Classe per gestire l'esecuzione del comando +dev+.
|
16
|
+
class Executable
|
17
|
+
|
18
|
+
##
|
19
|
+
# Definisce la classe per tutti gli errori interni
|
20
|
+
# all'esecuzione.
|
21
|
+
class ExecutionError < StandardError; end
|
22
|
+
|
23
|
+
include Dev::Executables::Commands::Version
|
24
|
+
include Dev::Executables::Commands::Status
|
25
|
+
include Dev::Executables::Commands::Feature
|
26
|
+
include Dev::Executables::Commands::Hotfix
|
27
|
+
include Dev::Executables::Commands::Release
|
28
|
+
include Dev::Executables::Commands::Pull
|
29
|
+
include Dev::Executables::Commands::Push
|
30
|
+
include Dev::Executables::Commands::Test
|
31
|
+
|
32
|
+
# @return [Dev::Executables::Project] il progetto di riferimento.
|
33
|
+
attr_accessor :project
|
34
|
+
# @return [StandardError] l'errore riscontrato, se presente.
|
35
|
+
attr_accessor :error
|
36
|
+
# @return [String] il backtrace dell'errore, se presente.
|
37
|
+
attr_accessor :backtrace
|
38
|
+
|
39
|
+
##
|
40
|
+
# Inizializza l'eseguibile, in base al comando passato.
|
41
|
+
#
|
42
|
+
# @param [Array] argv gli argomenti del comando.
|
43
|
+
def initialize(*argv)
|
44
|
+
begin
|
45
|
+
if argv[0].present?
|
46
|
+
if self.respond_to?(argv[0])
|
47
|
+
# Carica i dati del progetto
|
48
|
+
load_project
|
49
|
+
# Lancia il comando passato
|
50
|
+
if self.method(argv[0]).arity.abs > 0
|
51
|
+
self.send(argv[0], *argv[1..-1])
|
52
|
+
else
|
53
|
+
self.send(argv[0])
|
54
|
+
end
|
55
|
+
else
|
56
|
+
raise ExecutionError.new "Command '#{argv[0]}' is not supported. Run "\
|
57
|
+
"'dev help' for a list of available commands."
|
58
|
+
end
|
59
|
+
else
|
60
|
+
raise ExecutionError.new "Missing required parameters. Run 'dev help' "\
|
61
|
+
"for a list of available commands."
|
62
|
+
end
|
63
|
+
rescue Dev::Executable::ExecutionError => e
|
64
|
+
@error = e.message
|
65
|
+
puts @error.red
|
66
|
+
rescue StandardError => e
|
67
|
+
@error = "#{e.class}: #{e.message}"
|
68
|
+
@backtrace = e.backtrace.join("\n")
|
69
|
+
puts @error.red
|
70
|
+
puts @backtrace.red
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Carica i dati del progetto prendendoli dal file
|
76
|
+
# di configurazione del file 'dev.yml'.
|
77
|
+
#
|
78
|
+
# @return [nil]
|
79
|
+
def load_project
|
80
|
+
config_file = Dir.glob("#{Dir.pwd}/**/dev.yml").first
|
81
|
+
raise ExecutionError.new "No valid configuration files found. Searched for a file named 'dev.yml' "\
|
82
|
+
"in folder #{Dir.pwd} and all its subdirectories." if config_file.nil?
|
83
|
+
@project = Dev::Project.new(config_file)
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Determina de l'env è valido.
|
88
|
+
#
|
89
|
+
# @return [Boolean] se l'env è fra quelli validi.
|
90
|
+
def valid_env?
|
91
|
+
unless @env.in? [ :production, :staging ]
|
92
|
+
raise ExecutionError.new "The environment '#{@env}' is not valid. "\
|
93
|
+
"Valid environments are 'production' or 'staging'."
|
94
|
+
else
|
95
|
+
true
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
# Esegue un comando e cattura l'output ritornandolo come
|
101
|
+
# risultato di questo metodo. Si può passare l'opzione
|
102
|
+
# +flush+ per stampare subito l'output come se non fosse stato
|
103
|
+
# catturato.
|
104
|
+
#
|
105
|
+
# @param [String] command il comando da eseguire.
|
106
|
+
# @param [Hash] options le opzioni.
|
107
|
+
#
|
108
|
+
# @return [nil]
|
109
|
+
def exec(command, options = {})
|
110
|
+
out, err, status = Open3.capture3(command)
|
111
|
+
command_output = [ out.presence, err.presence ].compact.join("\n")
|
112
|
+
if options[:flush] == true
|
113
|
+
puts command_output
|
114
|
+
else
|
115
|
+
command_output
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
##
|
120
|
+
# Stampa i comandi possibili.
|
121
|
+
#
|
122
|
+
# @return [nil]
|
123
|
+
def help
|
124
|
+
puts
|
125
|
+
print "Dev".green
|
126
|
+
print " - available commands:\n"
|
127
|
+
puts
|
128
|
+
|
129
|
+
print "\tversion\t\t".limegreen
|
130
|
+
print "Prints current version.\n"
|
131
|
+
puts
|
132
|
+
|
133
|
+
print "\tfeature\t\t".limegreen
|
134
|
+
print "Opens or closes a feature for the current app.\n"
|
135
|
+
print "\t\t\tWarning: the app is determined from the current working directory!\n"
|
136
|
+
print "\t\t\tExample: "
|
137
|
+
print "dev feature open my-new-feature".springgreen
|
138
|
+
print " (opens a new feature for the current app)"
|
139
|
+
print ".\n"
|
140
|
+
print "\t\t\tExample: "
|
141
|
+
print "dev feature close my-new-feature".springgreen
|
142
|
+
print " (closes a developed new feature for the current app)"
|
143
|
+
print ".\n"
|
144
|
+
puts
|
145
|
+
|
146
|
+
print "\thotfix\t\t".limegreen
|
147
|
+
print "Opens or closes a hotfix for the current app.\n"
|
148
|
+
print "\t\t\tWarning: the app is determined from the current working directory!\n"
|
149
|
+
print "\t\t\tExample: "
|
150
|
+
print "dev hotfix open 0.2.1".springgreen
|
151
|
+
print " (opens a new hotfix for the current app)"
|
152
|
+
print ".\n"
|
153
|
+
print "\t\t\tExample: "
|
154
|
+
print "dev hotfix close 0.2.1".springgreen
|
155
|
+
print " (closes a developed new hotfix for the current app)"
|
156
|
+
print ".\n"
|
157
|
+
puts
|
158
|
+
|
159
|
+
print "\trelease\t\t".limegreen
|
160
|
+
print "Opens or closes a release for the current app.\n"
|
161
|
+
print "\t\t\tWarning: the app is determined from the current working directory!\n"
|
162
|
+
print "\t\t\tExample: "
|
163
|
+
print "dev release open 0.2.0".springgreen
|
164
|
+
print " (opens a new release for the current app)"
|
165
|
+
print ".\n"
|
166
|
+
print "\t\t\tExample: "
|
167
|
+
print "dev release close 0.2.0".springgreen
|
168
|
+
print " (closes a developed new release for the current app)"
|
169
|
+
print ".\n"
|
170
|
+
puts
|
171
|
+
|
172
|
+
print "\tpull\t\t".limegreen
|
173
|
+
print "Pulls specified app's git repository, or pulls all apps if none are specified.\n"
|
174
|
+
print "\t\t\tWarning: the pulled branch is the one the app is currently on!\n"
|
175
|
+
print "\t\t\tExample: "
|
176
|
+
print "dev pull [myapp]".springgreen
|
177
|
+
print ".\n"
|
178
|
+
puts
|
179
|
+
|
180
|
+
print "\tpush\t\t".limegreen
|
181
|
+
print "Commits and pushes the specified app.\n"
|
182
|
+
print "\t\t\tWarning: the pushed branch is the one the app is currently on!\n"
|
183
|
+
print "\t\t\tExample: "
|
184
|
+
print "dev push myapp \"commit message\"".springgreen
|
185
|
+
print ".\n"
|
186
|
+
puts
|
187
|
+
|
188
|
+
print "\ttest\t\t".limegreen
|
189
|
+
print "Runs the app's test suite. Tests must be written with rspec.\n"
|
190
|
+
print "\t\t\tIt is possibile to specify which app's test suite to run.\n"
|
191
|
+
print "\t\t\tIf nothing is specified, all main app's test suites are run.\n"
|
192
|
+
print "\t\t\tExample: "
|
193
|
+
print "dev test mymainapp myengine".springgreen
|
194
|
+
print " (runs tests for 'mymainapp' and 'myengine')"
|
195
|
+
print ".\n"
|
196
|
+
print "\t\t\tExample: "
|
197
|
+
print "dev test".springgreen
|
198
|
+
print " (runs tests for all main apps and engines within this project)"
|
199
|
+
print ".\n"
|
200
|
+
puts
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Dev
|
2
|
+
module Executables
|
3
|
+
module Commands
|
4
|
+
module Feature
|
5
|
+
|
6
|
+
##
|
7
|
+
# Comandi per gestire l'apertura e la chiusura di una nuova feature.
|
8
|
+
#
|
9
|
+
# @param [String] command il comando da eseguire.
|
10
|
+
# @param [String] name il nome della feature.
|
11
|
+
#
|
12
|
+
# @return [nil]
|
13
|
+
def feature(command = nil, name = nil)
|
14
|
+
raise Dev::Executable::ExecutionError.new "Wrong command syntax: "\
|
15
|
+
"specify whether to open or close a feature. "\
|
16
|
+
"Example: dev feature open my-new-feature" unless command.in? [ 'open', 'close' ]
|
17
|
+
name = name.to_s.squish
|
18
|
+
|
19
|
+
if @project.valid_app?
|
20
|
+
case command
|
21
|
+
when 'open' then feature_open(name)
|
22
|
+
when 'close' then feature_close(name)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# Apre una nuova feature.
|
29
|
+
#
|
30
|
+
# @param [String] name il nome della feature.
|
31
|
+
#
|
32
|
+
# @return [nil]
|
33
|
+
def feature_open(name)
|
34
|
+
print "Preparing to open a new feature for app "
|
35
|
+
print @project.current_app.teal
|
36
|
+
print " named "
|
37
|
+
puts name.teal
|
38
|
+
puts
|
39
|
+
|
40
|
+
branches = `git branch -a`
|
41
|
+
unless branches.include? ("develop\n")
|
42
|
+
print "\tCreating develop branch.."
|
43
|
+
exec "git checkout -b develop"
|
44
|
+
exec "git add ."
|
45
|
+
exec "git commit -m \"Dev: automatically created 'develop' branch\""
|
46
|
+
exec "git push -u origin develop"
|
47
|
+
print "√\n".green
|
48
|
+
puts
|
49
|
+
end
|
50
|
+
|
51
|
+
print "\tOpening.. "
|
52
|
+
git_output = exec "git checkout -b feature/#{name} develop"
|
53
|
+
if git_output.include?('fatal') or git_output.include?('rejected') or git_output.include?('error')
|
54
|
+
print "X\n".red
|
55
|
+
puts "\t\tSomething went wrong, take a look at the output from git:".indianred
|
56
|
+
puts "\t\t#{git_output.split("\n").map(&:squish).join("\n\t\t")}".indianred
|
57
|
+
puts
|
58
|
+
else
|
59
|
+
print "√\n".green
|
60
|
+
puts "\t\tDone. Output from git:".cadetblue
|
61
|
+
puts "\t\t#{git_output.split("\n").map(&:squish).join("\n\t\t")}".cadetblue
|
62
|
+
puts
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Chiude una feature esistente.
|
68
|
+
#
|
69
|
+
# @param [String] name il nome della feature.
|
70
|
+
#
|
71
|
+
# @return [nil]
|
72
|
+
def feature_close(name)
|
73
|
+
print "Preparing to close the feature for app "
|
74
|
+
print @project.current_app.teal
|
75
|
+
print " named "
|
76
|
+
puts name.teal
|
77
|
+
puts
|
78
|
+
|
79
|
+
status = `git status`
|
80
|
+
if status.include? "Changes not staged for commit:"
|
81
|
+
raise Dev::Executable::ExecutionError.new "Your current branch has unstaged changes. Please "\
|
82
|
+
"commit or stash them before closing the feature."
|
83
|
+
end
|
84
|
+
|
85
|
+
branches = `git branch -a`
|
86
|
+
unless branches.include? ("feature/#{name}\n")
|
87
|
+
raise Dev::Executable::ExecutionError.new "No feature named '#{name}' could be found "\
|
88
|
+
"for this app's repository."
|
89
|
+
end
|
90
|
+
|
91
|
+
print "\tClosing.. "
|
92
|
+
exec "git checkout develop"
|
93
|
+
exec "git merge --no-ff feature/#{name}"
|
94
|
+
git_output = exec "git push origin develop"
|
95
|
+
if git_output.include?('fatal') or git_output.include?('rejected') or git_output.include?('error')
|
96
|
+
print "X\n".red
|
97
|
+
puts "\t\tSomething went wrong, take a look at the output from git:".indianred
|
98
|
+
puts "\t\t#{git_output.split("\n").map(&:squish).join("\n\t\t")}".indianred
|
99
|
+
puts
|
100
|
+
else
|
101
|
+
print "√\n".green
|
102
|
+
puts "\t\tDone. Output from git:".cadetblue
|
103
|
+
puts "\t\t#{git_output.split("\n").map(&:squish).join("\n\t\t")}".cadetblue
|
104
|
+
puts
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|