geordi 5.2.1 → 5.4.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 19c9b8957b10e4c230a209bf34c89109a3ab669a2f240e626c86c9d5e1350382
4
- data.tar.gz: 05d90de73a7199c49ec904c3a5916755d36df91b15f7dd3cec5566d1a1ce3b78
3
+ metadata.gz: 87cda39f50721b8821dc5042de4a4ead24b4f8a27d5601bcb1742aa5f1a7cd00
4
+ data.tar.gz: baf33c3c575963062318374024cfae1071dd1002aaebbdd1c353cc7dc8c4c0c0
5
5
  SHA512:
6
- metadata.gz: a6db435c46379b64cebc89a724f58c9d90052fce49aa051050f2f74f229ad54d5eeae1ef6ee1d8fe187d1a1dc882a340c707658768e3cdfd524c2d7310a42737
7
- data.tar.gz: 8e1f5c65afba492ba83f2c47654207b7dfe648aeb752eea2f87e750667a51533098a84914429dd640ac98d529c078f45aaa7fdab2ca1967da99cefeb7cd123d4
6
+ metadata.gz: 0a66597a85f305bf90bf01ec56f0141ad4c3a7fcbd4d21032e8a7f64b2b5fece841e37084c8f783d7f8b9269e484d4cd7d6b35523435b032d67e472125c14043
7
+ data.tar.gz: 74954d6cf80dc9dea5b3f8d233fa2f2c2cb0c65fb229c385b96cb202f667dfdab14a1fd32212f3a168658cbeacbe4a279300a6a6fbcb9eee44f91a85b5da241f
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.5.8
1
+ 2.2
data/CHANGELOG.md CHANGED
@@ -1,25 +1,59 @@
1
1
  # Changelog
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
-
5
4
  This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
5
 
6
+
7
7
  ## Unreleased
8
8
 
9
9
  ### Compatible changes
10
10
 
11
11
  ### Breaking changes
12
12
 
13
- ## 5.2.1 2020-12-15
13
+
14
+ ## 5.4.0 2021-02-01
15
+
16
+ ### Compatible changes
17
+ * Add `geordi branch` command that checks out a feature branch based on a story from Pivotal Tracker
18
+ * Faster MySQL dumping with [`--single-transaction` and `--quick`](https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html#option_mysqldump_single-transaction)
19
+ * Allow pivotal tracker ids in the global config file
20
+ * Fix missing require for `Fileutils` in the dump load command (#145)
21
+ * Document `PARALLEL_TEST_PROCESSORS`
22
+
23
+
24
+ ## 5.3.0 2021-02-01
25
+
26
+ ### Compatible changes
27
+ * Changed: Dumping and loading a database will not keep the database dump in `tmp/` but delete it once the operation finishes successfully. Example: `geordi dump staging -l` will remove the file `tmp/staging.dump` after it loaded the dump.
28
+
29
+
30
+ ## 5.2.4 2021-01-29
31
+
32
+ ### Compatible changes
33
+ * Fix and improve delete-dumps command (now supporting multiple arguments)
34
+
35
+
36
+ ## 5.2.3 2021-01-27
37
+
38
+ ### Compatible changes
39
+ * Remove auto-bundling from `geordi shell` and remote `geordi console`
40
+
41
+
42
+ ## 5.2.2 2020-12-17
14
43
 
15
44
  ### Compatible changes
45
+ * Ignore ACL settings when loading a PostgreSQL dump
16
46
 
47
+
48
+ ## 5.2.1 2020-12-15
49
+
50
+ ### Compatible changes
17
51
  * Fix a bug regarding `geordi vnc` which was introduced in 5.1.0
18
52
 
53
+
19
54
  ## 5.2.0 2020-12-14
20
55
 
21
56
  ### Compatible changes
22
-
23
57
  * Geordi update will exit with a warning when Ruby version changes during pull.
24
58
  * Add `geordi docker` command with support for opening a shell for dockerized dev environments.
25
59
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- geordi (5.2.1)
4
+ geordi (5.3.0)
5
5
  thor (~> 1)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -25,6 +25,15 @@ You can always run `geordi help <command>` to quickly look up command help.
25
25
  Enable the given virtual host, disabling all others.
26
26
 
27
27
 
28
+ ### `geordi branch`
29
+ Check out a feature branch based on a story from Pivotal Tracker.
30
+
31
+ Example: `geordi branch`
32
+
33
+ On the first execution we ask for your Pivotal Tracker API token. It will be
34
+ stored in `~/.config/geordi/global.yml`.
35
+
36
+
28
37
  ### `geordi capistrano COMMAND`
29
38
  Run a capistrano command on all deploy targets.
30
39
 
@@ -100,6 +109,9 @@ sign, i.e. have each option a contiguous string.
100
109
  headless test browser anyway, you can disable VNC by setting `use_vnc: false`
101
110
  in `.geordi.yml` in the project root.
102
111
 
112
+ - In order to limit processes in a parallel run, you can set an environment
113
+ variable like this: `PARALLEL_TEST_PROCESSORS=6 geordi cucumber`
114
+
103
115
  **Options**
104
116
  - `-m, [--modified], [--no-modified]`: Run all modified features
105
117
  - `-c, [--containing=STRING]`: Run all features that contain STRING
@@ -111,13 +123,13 @@ in `.geordi.yml` in the project root.
111
123
  ### `geordi delete-dumps [DIRECTORY]`
112
124
  Delete database dump files (*.dump).
113
125
 
114
- Example: `geordi delete_dumps` or `geordi delete_dumps ~/tmp/dumps`
126
+ Example: `geordi delete-dumps` or `geordi delete-dumps ~/tmp/dumps`
115
127
 
116
- Recursively search for files ending in `*.dump` and offer to delete those. When
128
+ Recursively searches for files ending in `.dump` and offers to delete them. When
117
129
  no argument is given, two default directories are searched for dump files: the
118
130
  current working directory and `~/dumps` (for dumps created with geordi).
119
131
 
120
- Geordi will ask for confirmation before actually deleting files.
132
+ Will ask for confirmation before actually deleting files.
121
133
 
122
134
 
123
135
  ### `geordi deploy [STAGE]`
@@ -169,8 +181,11 @@ There are three subcommands:
169
181
 
170
182
  - `geordi docker setup`
171
183
  Fetches all docker containers.
184
+
172
185
  - `geordi docker shell`
173
186
  Runs the docker service named 'main'.
187
+ Append `--secondary` to open a second shell in an already running container.
188
+
174
189
  - `geordi docker vnc`
175
190
  Opens a VNC viewer to connect to the VNC server in the container.
176
191
 
@@ -278,7 +293,10 @@ Run RSpec.
278
293
 
279
294
  Example: `geordi rspec spec/models/user_spec.rb:13`
280
295
 
281
- Runs RSpec with RSpec 1/2 support, parallel_tests detection and `bundle exec`.
296
+ Runs RSpec with version 1/2 support, parallel_tests detection and `bundle exec`.
297
+
298
+ In order to limit processes in a parallel run, you can set an environment
299
+ variable like this: `PARALLEL_TEST_PROCESSORS=6 geordi rspec`
282
300
 
283
301
 
284
302
  ### `geordi security-update [STEP]`
@@ -423,11 +441,9 @@ Once you have completed your modifications, please update CHANGELOG and README
423
441
  as needed. Use `rake readme` to regenerate the Geordi section of the README from
424
442
  the command documentations.
425
443
 
426
- Make sure tests are green in the default Ruby *plus* in the oldest Ruby > 1.8
427
- that you have installed on your system (1.8.7 support has been dropped).
428
-
429
- Before releasing your changes, wait for the Travis results to see that tests
430
- passed in all Ruby versions.
444
+ Make sure tests are green in the oldest supported Ruby version. Before releasing
445
+ a new gem version, wait for the CI results to see that tests are green in all
446
+ Ruby versions.
431
447
 
432
448
 
433
449
  Adding a new command
data/exe/dumple CHANGED
@@ -78,6 +78,13 @@ begin
78
78
  command << " -p\"#{config['password']}\""
79
79
  command << " #{config['database']}"
80
80
  command << " -r #{dump_path}"
81
+ # Using a transaction to allow concurrent request while creating a dump.
82
+ # This works only reliable for InnoDB tables.
83
+ # More details: https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html#option_mysqldump_single-transaction
84
+ command << ' --single-transaction'
85
+ # Disable buffering in memory to avoid a memory overflow for large tables
86
+ # More details https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html#option_mysqldump_quick
87
+ command << ' --quick'
81
88
  if port
82
89
  command << " -h#{host || '127.0.0.1'} -P#{port}"
83
90
  else
@@ -0,0 +1,12 @@
1
+ desc 'branch', 'Check out a feature branch based on a story from Pivotal Tracker'
2
+ long_desc <<-LONGDESC
3
+ Example: `geordi branch`
4
+
5
+ On the first execution we ask for your Pivotal Tracker API token. It will be
6
+ stored in `~/.config/geordi/global.yml`.
7
+ LONGDESC
8
+
9
+ def branch
10
+ require 'geordi/gitpt'
11
+ Gitpt.new.run_branch
12
+ end
@@ -10,5 +10,5 @@ LONGDESC
10
10
 
11
11
  def commit(*git_args)
12
12
  require 'geordi/gitpt'
13
- Gitpt.new.run(git_args)
13
+ Gitpt.new.run_commit(git_args)
14
14
  end
@@ -14,9 +14,9 @@ option :select_server, type: :string, aliases: '-s', banner: '[SERVER_NUMBER]',
14
14
 
15
15
  def console(target = 'development', *_args)
16
16
  require 'geordi/remote'
17
- invoke_geordi 'bundle_install'
18
17
 
19
18
  if target == 'development'
19
+ invoke_geordi 'bundle_install'
20
20
  invoke_geordi 'yarn_install'
21
21
 
22
22
  Interaction.announce 'Opening a local Rails console'
@@ -20,6 +20,9 @@ sign, i.e. have each option a contiguous string.
20
20
  - *VNC:* By default, test browsers will run in a VNC session. When using a
21
21
  headless test browser anyway, you can disable VNC by setting `use_vnc: false`
22
22
  in `.geordi.yml` in the project root.
23
+
24
+ - In order to limit processes in a parallel run, you can set an environment
25
+ variable like this: `PARALLEL_TEST_PROCESSORS=6 geordi cucumber`
23
26
  LONGDESC
24
27
 
25
28
  option :modified, aliases: '-m', type: :boolean,
@@ -1,43 +1,41 @@
1
1
  desc 'delete-dumps [DIRECTORY]', 'Delete database dump files (*.dump)'
2
2
  long_desc <<-LONGDESC
3
- Example: `geordi delete_dumps` or `geordi delete_dumps ~/tmp/dumps`
3
+ Example: `geordi delete-dumps` or `geordi delete-dumps ~/tmp/dumps`
4
4
 
5
- Recursively search for files ending in `*.dump` and offer to delete those. When
5
+ Recursively searches for files ending in `.dump` and offers to delete them. When
6
6
  no argument is given, two default directories are searched for dump files: the
7
7
  current working directory and `~/dumps` (for dumps created with geordi).
8
8
 
9
- Geordi will ask for confirmation before actually deleting files.
9
+ Will ask for confirmation before actually deleting files.
10
10
  LONGDESC
11
11
 
12
- def delete_dumps(dump_directory = nil)
13
- deletable_dumps = []
14
- dump_directories = if dump_directory.nil?
15
- [
16
- File.join(Dir.home, 'dumps'),
17
- Dir.pwd,
18
- ]
19
- else
20
- [dump_directory]
12
+ def delete_dumps(*locations)
13
+ Interaction.announce 'Retrieving dump files'
14
+
15
+ dump_files = []
16
+ if locations.empty?
17
+ locations = [ File.join(Dir.home, 'dumps'), Dir.pwd ]
21
18
  end
22
- Interaction.announce 'Looking for *.dump in ' << dump_directories.join(',')
23
- dump_directories.each do |d|
24
- d_2 = File.expand_path(d)
25
- unless File.directory? File.realdirpath(d_2)
26
- Interaction.warn "Directory #{d_2} does not exist"
19
+ locations.map! &File.method(:expand_path)
20
+
21
+ Interaction.note "Looking in #{locations.join(', ')}"
22
+ locations.each do |dir|
23
+ directory = File.expand_path(dir)
24
+ unless File.directory? File.realdirpath(directory)
25
+ Interaction.warn "Directory #{directory} does not exist. Skipping."
27
26
  next
28
27
  end
29
- deletable_dumps.concat(Dir.glob("#{d_2}/**/*.dump"))
28
+ dump_files.concat Dir.glob("#{directory}/**/*.dump")
30
29
  end
30
+ deletable_dumps = dump_files.flatten.uniq.sort.select &File.method(:file?)
31
+
31
32
  if deletable_dumps.empty?
32
- Interaction.success 'No dumps to delete' if deletable_dumps.empty?
33
- exit 0
34
- end
35
- deletable_dumps.uniq!.sort!
36
- Interaction.note 'The following dumps can be deleted:'
37
- puts
38
- puts deletable_dumps
39
- Interaction.prompt('Delete those dumps', 'n', /y|yes/) || raise('Cancelled.')
40
- deletable_dumps.each do |dump|
41
- File.delete dump unless File.directory? dump
33
+ Interaction.note 'No dump files found'
34
+ else
35
+ puts deletable_dumps
36
+ Interaction.prompt('Delete these files?', 'n', /y|yes/) || Interaction.fail('Cancelled.')
37
+
38
+ deletable_dumps.each &File.method(:delete)
39
+ Interaction.success 'Done.'
42
40
  end
43
41
  end
@@ -1,17 +1,17 @@
1
1
  class DockerCLI < Thor
2
- desc 'setup', 'Setup docker and fetch required docker-container for the current project.'
2
+ desc 'setup', 'Setup docker and fetch required docker-container for the current project'
3
3
  def setup
4
4
  docker.setup
5
5
  end
6
6
 
7
- desc 'shell', 'Open a shell in the main docker container for the current project.'
7
+ desc 'shell', 'Open a shell in the main docker container for the current project'
8
8
  option :secondary, default: false, type: :boolean
9
9
  map 'shell' => '_shell'
10
10
  def _shell
11
11
  docker.shell(:secondary => options[:secondary])
12
12
  end
13
13
 
14
- desc 'vnc', 'Open a vnc viewer connecting to the docker container.'
14
+ desc 'vnc', 'Open a vnc viewer connecting to the docker container'
15
15
  def vnc
16
16
  docker.vnc
17
17
  end
@@ -24,7 +24,7 @@ class DockerCLI < Thor
24
24
  end
25
25
  end
26
26
 
27
- desc 'docker', 'Manage docker containers for the current project.'
27
+ desc 'docker', 'Manage docker containers for the current project'
28
28
  long_desc <<-LONGDESC
29
29
  Manage docker containers to run your project dockerized.
30
30
 
@@ -35,10 +35,12 @@ There are three subcommands:
35
35
 
36
36
  - `geordi docker setup`
37
37
  Fetches all docker containers.
38
+
38
39
  - `geordi docker shell`
39
40
  Runs the docker service named 'main'.
41
+ Append `--secondary` to open a second shell in an already running container.
42
+
40
43
  - `geordi docker vnc`
41
44
  Opens a VNC viewer to connect to the VNC server in the container.
42
-
43
45
  LONGDESC
44
46
  subcommand 'docker', DockerCLI
@@ -57,6 +57,9 @@ def dump(target = nil, *_args)
57
57
  Interaction.announce "Sourcing dump into the #{loader.config['database']} db"
58
58
  loader.load
59
59
 
60
+ Util.run! "rm #{dump_path}"
61
+ Interaction.note "Dump file removed"
62
+
60
63
  Interaction.success "Your #{loader.config['database']} database has now the data of #{target}#{database_label}."
61
64
  end
62
65
  end
@@ -2,7 +2,10 @@ desc 'rspec [FILES]', 'Run RSpec'
2
2
  long_desc <<-LONGDESC
3
3
  Example: `geordi rspec spec/models/user_spec.rb:13`
4
4
 
5
- Runs RSpec with RSpec 1/2 support, parallel_tests detection and `bundle exec`.
5
+ Runs RSpec with version 1/2 support, parallel_tests detection and `bundle exec`.
6
+
7
+ In order to limit processes in a parallel run, you can set an environment
8
+ variable like this: `PARALLEL_TEST_PROCESSORS=6 geordi rspec`
6
9
  LONGDESC
7
10
 
8
11
  def rspec(*files)
@@ -15,8 +15,6 @@ option :select_server, type: :string, aliases: '-s', banner: '[SERVER_NUMBER]',
15
15
  def shelll(target, *_args)
16
16
  require 'geordi/remote'
17
17
 
18
- invoke_geordi 'bundle_install'
19
-
20
18
  Interaction.announce 'Opening a shell on ' + target
21
19
  Geordi::Remote.new(target).shell(options)
22
20
  end
@@ -60,7 +60,7 @@ module Geordi
60
60
  VNC_ENV_VARIABLES.each do |variable|
61
61
  ENV["OUTER_#{variable}"] = ENV[variable] if ENV[variable]
62
62
  end
63
- ENV['BROWSER'] = ENV['LAUNCHY_BROWSER'] = File.expand_path('../../bin/launchy_browser', __dir__)
63
+ ENV['BROWSER'] = ENV['LAUNCHY_BROWSER'] = File.expand_path('../../exe/launchy_browser', __dir__)
64
64
  ENV['DISPLAY'] = VNC_DISPLAY
65
65
 
66
66
  Interaction.note 'Run `geordi vnc` to view the Selenium test browsers'
@@ -34,7 +34,7 @@ module Geordi
34
34
 
35
35
  def postgresql_command
36
36
  ENV['PGPASSWORD'] = config['password']
37
- command = 'pg_restore --no-owner --clean'
37
+ command = 'pg_restore --no-owner --clean --no-acl'
38
38
  command << ' --username=' << config['username'].to_s if config['username']
39
39
  command << ' --port=' << config['port'].to_s if config['port']
40
40
  command << ' --host=' << config['host'].to_s if config['host']
@@ -57,7 +57,7 @@ module Geordi
57
57
  Interaction.note 'Source file: ' + dump_file
58
58
 
59
59
  source_command = send("#{config['adapter']}_command")
60
- Util.run! source_command, fail_message: "An error occured loading #{File.basename(dump_file)}"
60
+ Util.run! source_command, fail_message: "An error occurred loading #{File.basename(dump_file)}"
61
61
  end
62
62
 
63
63
  end
data/lib/geordi/gitpt.rb CHANGED
@@ -1,99 +1,170 @@
1
- class Gitpt
2
- require 'yaml'
3
- require 'highline'
4
- require 'tracker_api'
5
-
6
- # This require-style is to prevent Ruby from loading files of a different
7
- # version of Geordi.
8
- require File.expand_path('settings', __dir__)
9
-
10
- def initialize
11
- self.highline = HighLine.new
12
- self.settings = Geordi::Settings.new
13
- self.client = build_client
14
- end
1
+ require 'yaml'
2
+ require 'highline'
3
+ require 'tracker_api'
4
+
5
+ module Geordi
6
+ class Gitpt
7
+
8
+ # This require-style is to prevent Ruby from loading files of a different
9
+ # version of Geordi.
10
+ require File.expand_path('settings', __dir__)
15
11
 
16
- def run(git_args)
17
- Geordi::Interaction.warn <<-WARNING unless Geordi::Util.staged_changes?
12
+ def initialize
13
+ self.highline = HighLine.new
14
+ self.settings = Settings.new
15
+ self.client = build_client
16
+ end
17
+
18
+ def run_commit(git_args)
19
+ Interaction.warn <<-WARNING unless Util.staged_changes?
18
20
  No staged changes. Will create an empty commit.
19
- WARNING
21
+ WARNING
20
22
 
21
- story = choose_story
22
- if story
23
- create_commit "[##{story.id}] #{story.name}", *git_args
23
+ story = choose_story
24
+ if story
25
+ create_commit "[##{story.id}] #{story.name}", *git_args
26
+ end
24
27
  end
25
- end
26
28
 
27
- private
29
+ def run_branch
30
+ story = choose_story || Interaction.fail('No story selected.')
28
31
 
29
- attr_accessor :highline, :client, :settings
32
+ normalized_story_name = normalize_string(story.name)
30
33
 
31
- def build_client
32
- TrackerApi::Client.new(token: settings.pivotal_tracker_api_key)
33
- end
34
+ branch_list_string = if Util.testing?
35
+ ENV['GEORDI_TESTING_GIT_BRANCHES'] || ''
36
+ else
37
+ `git branch --format="%(refname:short)"`
38
+ end
34
39
 
35
- def load_projects
36
- project_ids = settings.pivotal_tracker_project_ids
37
- project_ids.collect { |project_id| client.project(project_id) }
38
- end
40
+ if branch_list_string.nil? || branch_list_string.strip.empty?
41
+ Interaction.fail 'Could not determine local git branches.'
42
+ end
39
43
 
40
- def applicable_stories
41
- projects = load_projects
42
- projects.collect do |project|
43
- project.stories(filter: 'state:started,finished,rejected')
44
- end.flatten
45
- end
44
+ new_branch_name = "#{git_user_initials}/#{normalized_story_name}-#{story.id}"
45
+
46
+ local_branches = branch_list_string.split("\n")
47
+ branch_name = local_branches.find { |branch_name| branch_name == new_branch_name }
48
+ branch_name ||= local_branches.find { |branch_name| branch_name.include? story.id.to_s }
49
+
50
+ if branch_name.present?
51
+ checkout_branch branch_name, new_branch: false
52
+ else
53
+ checkout_branch new_branch_name, new_branch: true
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ attr_accessor :highline, :client, :settings
60
+
61
+ def build_client
62
+ TrackerApi::Client.new(token: settings.pivotal_tracker_api_key)
63
+ end
64
+
65
+ def load_projects
66
+ project_ids = settings.pivotal_tracker_project_ids
67
+ project_ids.collect { |project_id| client.project(project_id) }
68
+ end
46
69
 
47
- def choose_story
48
- if Geordi::Util.testing?
49
- return OpenStruct.new(id: 12, name: 'Test Story')
70
+ def applicable_stories
71
+ projects = load_projects
72
+ projects.collect do |project|
73
+ project.stories(filter: 'state:started,finished,rejected')
74
+ end.flatten
50
75
  end
51
76
 
52
- loading_message = 'Connecting to Pivotal Tracker ...'
53
- print(loading_message)
54
- stories = applicable_stories
55
- reset_loading_message = "\r#{' ' * (loading_message.length + stories.length)}\r"
77
+ def choose_story
78
+ if Util.testing?
79
+ return OpenStruct.new(id: 12, name: 'Test Story')
80
+ end
81
+
82
+ loading_message = 'Connecting to Pivotal Tracker ...'
83
+ print(loading_message)
84
+ stories = applicable_stories
85
+ reset_loading_message = "\r#{' ' * (loading_message.length + stories.length)}\r"
86
+
87
+ highline.choose do |menu|
88
+ menu.header = 'Choose a story'
89
+
90
+ stories.each do |story|
91
+ print '.' # Progress
92
+
93
+ state = story.current_state
94
+ owners = story.owners
95
+ owner_is_me = owners.collect(&:id).include?(client.me.id)
56
96
 
57
- highline.choose do |menu|
58
- menu.header = 'Choose a story'
97
+ if state == 'started'
98
+ state = HighLine::GREEN + state + HighLine::RESET
99
+ elsif state != 'finished'
100
+ state = HighLine::RED + state + HighLine::RESET
101
+ end
59
102
 
60
- stories.each do |story|
61
- print '.' # Progress
103
+ state += HighLine::BOLD if owner_is_me
62
104
 
63
- state = story.current_state
64
- owners = story.owners
65
- owner_is_me = owners.collect(&:id).include?(client.me.id)
105
+ label = "(#{owners.collect(&:name).join(', ')}, #{state}) #{story.name}"
106
+ label = bold(label) if owner_is_me
66
107
 
67
- if state == 'started'
68
- state = HighLine::GREEN + state + HighLine::RESET
69
- elsif state != 'finished'
70
- state = HighLine::RED + state + HighLine::RESET
108
+ menu.choice(label) { return story }
71
109
  end
72
110
 
73
- state += HighLine::BOLD if owner_is_me
111
+ menu.hidden ''
112
+ print reset_loading_message # Once menu is build
113
+ end
114
+
115
+ nil # Return nothing
116
+ end
74
117
 
75
- label = "(#{owners.collect(&:name).join(', ')}, #{state}) #{story.name}"
76
- label = bold(label) if owner_is_me
118
+ def create_commit(message, *git_args)
119
+ extra = highline.ask("\nAdd an optional message").strip
120
+ message << ' - ' << extra if extra != ''
121
+
122
+ Util.run!(['git', 'commit', '--allow-empty', '-m', message, *git_args])
123
+ end
77
124
 
78
- menu.choice(label) { return story }
125
+ def bold(string)
126
+ HighLine::BOLD + string + HighLine::RESET
127
+ end
128
+
129
+ def checkout_branch(name, new_branch: false)
130
+ if new_branch
131
+ Util.run! ['git', 'checkout', 'master']
132
+ Util.run! ['git', 'checkout', '-b', name]
133
+ else
134
+ Util.run! ['git', 'checkout', name]
79
135
  end
136
+ end
80
137
 
81
- menu.hidden ''
82
- print reset_loading_message # Once menu is build
138
+ def normalize_string(name)
139
+ name.gsub!('ä', 'ae')
140
+ name.gsub!('ö', 'oe')
141
+ name.gsub!('ü', 'ue')
142
+ name.gsub!('ß', 'ss')
143
+ name.tr!('^A-Za-z0-9_ ', '')
144
+ name.squeeze! ' '
145
+ name.gsub!(' ', '-')
146
+ name.downcase!
147
+ name
83
148
  end
84
149
 
85
- nil # Return nothing
86
- end
150
+ def git_user_initials
151
+ stdout_str = if Util.testing?
152
+ ENV['GEORDI_TESTING_GIT_USERNAME']
153
+ else
154
+ `git config user.name`
155
+ end
87
156
 
88
- def create_commit(message, *git_args)
89
- extra = highline.ask("\nAdd an optional message").strip
90
- message << ' - ' << extra if extra != ''
157
+ git_user_initials = unless stdout_str.nil?
158
+ stdout_str.strip.split(' ').map(&:chars).map(&:first).join.downcase
159
+ end
91
160
 
92
- Geordi::Util.run!(['git', 'commit', '--allow-empty', '-m', message, *git_args])
93
- end
161
+ git_user_initials = Interaction.prompt 'Enter your initals:', git_user_initials
94
162
 
95
- def bold(string)
96
- HighLine::BOLD + string + HighLine::RESET
163
+ if git_user_initials.nil?
164
+ Interaction.fail('Could not determine the git user\'s initials.')
165
+ else
166
+ git_user_initials
167
+ end
168
+ end
97
169
  end
98
-
99
170
  end
data/lib/geordi/remote.rb CHANGED
@@ -3,6 +3,7 @@ require 'geordi/interaction'
3
3
  require 'geordi/util'
4
4
  require 'highline/import'
5
5
  require 'pathname'
6
+ require 'fileutils'
6
7
 
7
8
  module Geordi
8
9
  class Remote
@@ -59,7 +60,7 @@ module Geordi
59
60
  server_option = options[:select_server]
60
61
  server_number = server_option.to_i
61
62
 
62
- server = if server_option == 'select_server'
63
+ server = if server_option == 'select_server'
63
64
  select_server
64
65
  elsif server_number != 0 && server_number <= @config.servers.count
65
66
  server_index = server_number - 1
@@ -8,7 +8,7 @@ module Geordi
8
8
  GLOBAL_SETTINGS_FILE_NAME = Util.testing? ? './tmp/global_settings.yml'.freeze : File.join(ENV['HOME'], '.config/geordi/global.yml').freeze
9
9
  LOCAL_SETTINGS_FILE_NAME = Util.testing? ? './tmp/local_settings.yml'.freeze : './.geordi.yml'.freeze
10
10
 
11
- ALLOWED_GLOBAL_SETTINGS = %w[ pivotal_tracker_api_key auto_update_chromedriver ].freeze
11
+ ALLOWED_GLOBAL_SETTINGS = %w[ pivotal_tracker_api_key auto_update_chromedriver pivotal_tracker_project_ids ].freeze
12
12
  ALLOWED_LOCAL_SETTINGS = %w[ use_vnc pivotal_tracker_project_ids ].freeze
13
13
 
14
14
  def initialize
@@ -42,18 +42,13 @@ module Geordi
42
42
  end
43
43
 
44
44
  def pivotal_tracker_project_ids
45
- project_ids = @local_settings['pivotal_tracker_project_ids'] || pt_project_ids_old
45
+ local_project_ids = @local_settings['pivotal_tracker_project_ids'] || pt_project_ids_old
46
+ global_project_ids = @global_settings['pivotal_tracker_project_ids']
46
47
 
47
- case project_ids
48
- when Array
49
- # nothing to do
50
- when String
51
- project_ids = project_ids.split(/[\s]+/).map(&:to_i)
52
- when Integer
53
- project_ids = [project_ids]
54
- else
55
- project_ids = []
56
- end
48
+ local_project_ids = array_wrap_project_ids(local_project_ids)
49
+ global_project_ids = array_wrap_project_ids(global_project_ids)
50
+
51
+ project_ids = local_project_ids | global_project_ids
57
52
 
58
53
  if project_ids.empty?
59
54
  puts
@@ -160,5 +155,18 @@ module Geordi
160
155
  end
161
156
  end
162
157
 
158
+ def array_wrap_project_ids(project_ids)
159
+ case project_ids
160
+ when Array
161
+ project_ids
162
+ when String
163
+ project_ids.split(/[\s]+/).map(&:to_i)
164
+ when Integer
165
+ [project_ids]
166
+ else
167
+ []
168
+ end
169
+ end
170
+
163
171
  end
164
172
  end
data/lib/geordi/util.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'geordi/interaction'
2
2
  require 'socket'
3
+ require 'bundler'
3
4
 
4
5
  module Geordi
5
6
  class Util
@@ -167,15 +168,10 @@ module Geordi
167
168
  # Get the version for the given gem by parsing Gemfile.lock.
168
169
  # Returns nil if the gem is not used.
169
170
  def gem_version(gem)
170
- # Lines look like `* will_paginate (2.3.15)` or `railslts-version (2.3.18.16 7f51cc7)`
171
- bundle_list.split("\n").each do |line|
172
- matches = line.match(/\* #{gem} \(([\d\.]+)/)
173
- next if matches.nil? || matches[1].nil?
171
+ lock_file = Bundler::LockfileParser.new(Bundler.read_file(Bundler.default_lockfile))
172
+ spec = lock_file.specs.detect { |spec| spec.name == gem }
174
173
 
175
- return Gem::Version.new(matches[1])
176
- end
177
-
178
- nil
174
+ spec && spec.version
179
175
  end
180
176
 
181
177
  def file_containing?(file, regex)
@@ -192,12 +188,6 @@ module Geordi
192
188
  string
193
189
  end
194
190
 
195
- private
196
-
197
- def bundle_list
198
- @bundle_list ||= `bundle list`
199
- end
200
-
201
191
  end
202
192
  end
203
193
  end
@@ -1,3 +1,3 @@
1
1
  module Geordi
2
- VERSION = '5.2.1'.freeze
2
+ VERSION = '5.4.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geordi
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.1
4
+ version: 5.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henning Koch
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-16 00:00:00.000000000 Z
11
+ date: 2021-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -57,6 +57,7 @@ files:
57
57
  - lib/geordi/cli.rb
58
58
  - lib/geordi/commands/_setup_vnc.rb
59
59
  - lib/geordi/commands/apache_site.rb
60
+ - lib/geordi/commands/branch.rb
60
61
  - lib/geordi/commands/bundle_install.rb
61
62
  - lib/geordi/commands/capistrano.rb
62
63
  - lib/geordi/commands/chromedriver_update.rb