Skip to content

Commit

Permalink
Merge pull request #6 from gangelo/development
Browse files Browse the repository at this point in the history
Miscellaneous changes
  • Loading branch information
gangelo authored Sep 24, 2022
2 parents a74bbe3 + 4a4cbb5 commit 55b3c91
Show file tree
Hide file tree
Showing 14 changed files with 190 additions and 41 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## ['2.2.0'] - 2022-09-24
* Enhancements:
* Add support for `branch-name create` `-x` argument (see `branch-name help create`) which allows you to position the ticket and ticket description within the forulated branch name.
* The `branch-name create :project_location` option string now accepts any [`Time.strftime`](`https://apidock.com/ruby/Time/strftime`) format directive.
* Add better test coverage, although not what it should be (I'm working on it); this started a "quick and dirty" tool.
* `branch-name create` will now create the PROJECT_LOCATION if it does not exist.
* Update README.md file.

## ['2.1.0'] - 2022-09-22
* Enhancements: Add support for Windows clipboard. Branch names created are copied to the clibboard for macOS and Windows now.

Expand Down
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
branch-name (2.1.0)
branch-name (2.2.0)
activesupport (~> 7.0, >= 7.0.4)
colorize (~> 0.8.1)
os (~> 1.1, >= 1.1.4)
Expand Down
22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,33 +42,37 @@ $ branch-name config init global
#=> Configuration file (/Users/<username>/.branch-name) created
```

This creates a `.branch-name` .yaml configuration file the home folder of the current user (`$ whoami` on *macOS*) with the following option defaults. The option defaults created will be used with their respective `branch-name` command indicated by the `branch-name` command name under which each option resides. You may manually alter any of the option values to suite your needs. To determine what options are available for each `branch-name` command, simply view help for that particular command. If a `brnch-name` command is *not* found in the `.branch-name` confg file when it is first initialized (e.g. `$ branch-name config init global #=> /Users/<username>/.branch-name`), default options for that particular `branch-name` command are not currently supported.
This creates a `.branch-name` yaml configuration file the home folder of the current user (`$ whoami` on *macOS*) with the below option defaults. The option defaults created will be used with their respective `branch-name` command indicated by the `branch-name` command name under which each option resides. You may manually alter any of the option values to suite your needs. To determine what options are available for each `branch-name` command, simply view help for that particular command. If a `branch-name` command is *not* found in the `.branch-name` config file when it is first initialized (e.g. `$ branch-name config init global #=> /Users/<username>/.branch-name`), default options for that particular `branch-name` command are not currently supported.

For example, the following default options will be used whenever the `branch-name create` command is executed for the user "`<username>`":
Below is a list of _default_ options created when initializing _global_ options; consequently, these default options will be used whenever the `branch-name create` command is executed for the user "`<username>`":

```yaml
# /Users/<username>/.branch-name
---
create:
downcase: false
separator: _
format_string: "%t %d"
project: false
project_location: "/Users/<username>"
project_location: "/Users/<username>/branch-name/projects/%Y/%m (%B)"
project_files:
- scratch.rb
- readme.txt
- scratch.rb
- snippets.rb
```
NOTE: It is recommended that you change the default `create: project_location` to a more suitable location depending on your *os*. For example, on *macOS* you might want to change this to `"/Users/<username>/Documents"`, `"/Users/<username>/Documents/features"`, or something similar.
NOTE: You can manually change any of the options you wish. It is recommended that you change the default `create: project_location` to meet your needs, depending on your *os*. For example, on *macOS* you might want to change this to `"/Users/<username>/Documents"`, `"/Users/<username>/Documents/features"`, or something similar.

The `create: project_location` option string also accepts any [`Time.strftime`](`https://apidock.com/ruby/Time/strftime`) format directives.

Any or all of these options can be overwritten on the command-line:
The `create: format_string` option string can be used to position the *ticket* (`%t`) and *ticket description* (`%d`) within the branch name formulated. You can also include any other information you wish in the format string, for example: "`<username> %t %d`". However, non-word characters will be stripped (see `Branch::Name::Normalizable::NON_WORD_CHARS_REGEX` which equates to `/[\W_]/`)

For more information:
Any or all of these options can also be overwritten on the command-line. For more information:
`$ branch-name config help init`

### Creating Feature Branch Names and Projects Examples

NOTE: `branch-name create` really doesn't "create" anything (unless you use the `-p` option, in which case it will create a "project" for you); rather, `branch-name create` simply formulates a suitable feature branch name given a *jira* ticket and *jira* ticket description.
NOTE: `branch-name create` really doesn't "create" anything (unless you use the `-p` option, in which case it will create a "project" for you); rather, `branch-name create` simply _formulates_ a suitable feature branch name given a *jira* ticket and *jira* ticket description.

NOTE: The below examples will assume the following `global` config file defaults (`$ branch-name config init global`) that have been *manually* manipulated to have the following options:

Expand All @@ -79,7 +83,7 @@ create:
downcase: false
separator: _
project: false
project_location: "/Users/<username>/feature-branches/2022"
project_location: "/Users/<username>/feature-branches/%Y"
project_files:
- readme.txt
- scratch.rb
Expand Down
15 changes: 13 additions & 2 deletions lib/branch/name/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class CLI < ::Thor
SYNOPSIS
\x5
branch-name create [-l|-f|-d|-s|-p] DESCRIPTION [TICKET]
branch-name create [-l|-f|-d|-s|-p|-x] DESCRIPTION [TICKET]
\x5
The following options are available:
Expand All @@ -69,9 +69,17 @@ class CLI < ::Thor
A "project" is a folder that is created in the PROJECT_LOCATION specified,
whose name is equivalent to the branch name that is formulated.
The default is: "#{Locatable.project_folder(options: options)}".
\x5 -x FORMAT_STRING: This is a string that determines the format of the branch name
that is formulated. The following are a list of required placeholders you must put
in your format string to format the brach name: [%t, %d].
\x5Where %t will be replaced by the ticket.
\x5Where %d will be replaced by the ticket description.
\x5The default is: "#{DEFAULT_BRANCH_NAME_OPTIONS['create']['format_string']}".
LONG_DESC
method_option :downcase, type: :boolean, aliases: '-d'
method_option :separator, type: :string, aliases: '-s'
method_option :format_string, type: :string, aliases: '-x'
method_option :project, type: :boolean, aliases: '-p'
method_option :project_location, type: :string, aliases: '-l'
method_option :project_files, type: :array, aliases: '-f'
Expand All @@ -84,7 +92,10 @@ def create(ticket_description, ticket = nil)

init_options_for! command: :create

branch_name = normalize_branch_name(ticket_description, ticket)
branch_name = normalize_branch_name(ticket_description, ticket) do |error|
say_error error.message
exit 1
end

say "Branch name: #{branch_name}", :cyan

Expand Down
1 change: 0 additions & 1 deletion lib/branch/name/clipable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ def copy_to_clipboard(text)

def copy_to_clipboard_macos(text)
copy_to_clipboard_with(app: 'pbcopy', text: text)

end

def copy_to_clipboard_windows(text)
Expand Down
3 changes: 2 additions & 1 deletion lib/branch/name/configurable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ module Configurable
'create' => {
'downcase' => false,
'separator' => '_',
'format_string' => '%t %d',
'project' => false,
'project_location' => Locatable.project_folder,
'project_location' => "#{Locatable.project_folder}/branch-name/projects/%Y/%m (%B)",
'project_files' => %w[readme.txt scratch.rb snippets.rb]
}
}.freeze
Expand Down
29 changes: 25 additions & 4 deletions lib/branch/name/normalizable.rb
Original file line number Diff line number Diff line change
@@ -1,25 +1,46 @@
# frozen_string_literal: true

require_relative 'option_error'

module Branch
module Name
module Normalizable
NON_WORD_CHARS_REGEX = /[\W_]/

def normalize_branch_name(ticket_description, ticket)
normalized_ticket_description = normalize_ticket_description ticket_description
return normalized_ticket_description if ticket.blank?
formatted_branch_name = format_string_or_default
formatted_branch_name = formatted_branch_name.gsub('%t', ticket || '')
formatted_branch_name = formatted_branch_name.gsub('%d', ticket_description)
formatted_branch_name = normalize_token formatted_branch_name
rescue Branch::Name::OptionError => e
raise unless block_given?

normalized_ticket = normalize_ticket ticket
"#{normalized_ticket}#{options[:separator]}#{normalized_ticket_description}"
yield e
end

private

def format_string_or_default
format_string = options[:format_string].presence ||
Configurable::DEFAULT_BRANCH_NAME_OPTIONS['create']['format_string']
unless %w[%t %d].all? { |o| format_string.include?(o) }
raise Branch::Name::OptionError.new(
'was called having argument [-x/--format-string] ' \
'which did not contain %t and %d format placeholders',
current_command_chain.first
)
end

format_string
end

def normalize_ticket_description(ticket_description)
normalize_token ticket_description
end

def normalize_ticket(ticket)
return if ticket.blank?

ticket.split(NON_WORD_CHARS_REGEX).filter_map do |token|
normalize_token(token)
end.join(options[:separator])
Expand Down
19 changes: 19 additions & 0 deletions lib/branch/name/option_error.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

module Branch
module Name
class OptionError < StandardError
attr_reader :command

def initialize(msg, command)
super(msg)

@command = command
end

def message
"ERROR: \"branch-name #{command}\" #{super}"
end
end
end
end
5 changes: 3 additions & 2 deletions lib/branch/name/projectable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ module Projectable
def create_project!(branch_name)
raise 'options[:project] is false' unless options[:project]

project_folder = "#{options[:project_location]}/#{branch_name}"
project_location = Time.new.strftime(options[:project_location])
project_folder = "#{project_location}/#{branch_name}"

if Dir.exist? project_folder
puts "Project folder \"#{project_folder}\" already exists"
create_project_files!(project_folder)
return
end

Dir.mkdir project_folder
FileUtils.mkdir_p(project_folder)
create_project_files!(project_folder)

puts "Project folder \"#{project_folder}\" with project files #{options[:project_files]} was created".green
Expand Down
2 changes: 1 addition & 1 deletion lib/branch/name/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
module Branch
module Name
# branch-name version
VERSION = '2.1.0'
VERSION = '2.2.0'
end
end
1 change: 0 additions & 1 deletion spec/branch/name/clipable_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
end

after do
binding.pry
described_class.copy_to_clipboard('text')
end

Expand Down
103 changes: 103 additions & 0 deletions spec/branch/name/normalizable_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# frozen_string_literal: true

RSpec.shared_examples 'it formats the branch name properly' do
it 'formats the branch name properly' do
expect(subject).to eq branch_name
end
end

RSpec.shared_examples 'the format_string is invalid' do
it 'raises an error' do
expected_error = /did not contain %t and %d format placeholders/
expect { subject }.to raise_error(expected_error)
end
end

RSpec.describe Branch::Name::Normalizable, type: :module do
subject(:normalizable) do
Class.new do
include Branch::Name::Normalizable

attr_reader :options

def initialize(options)
@options = Thor::CoreExt::HashWithIndifferentAccess.new(options)
end

def current_command_chain
[:some_command]
end
end.new(options).normalize_branch_name(ticket_description, ticket)
end

let(:default_options) do
{
downcase: false,
separator: '_',
format_string: '%t %d',
project: false,
project_location: temp_directory.to_s,
project_files: %w[readme.txt scratch.rb snippets.rb]
}
end
let(:ticket) { 'TICKET-12345' }
let(:ticket_description) { 'Ticket Description' }
let(:temp_directory) { Dir.tmpdir }

describe '#normalize_branch_name' do
let(:branch_name) { 'TICKET_12345_Ticket_Description' }

context 'with downcase option' do
context 'when false' do
let(:options) { default_options }

it 'formulates a branch name that is lowercase' do
expect(subject).to eq branch_name
end
end

context 'when true' do
let(:options) { default_options.merge({ downcase: true }) }

it 'formulates a branch name that is lowercase' do
expect(subject).to eq branch_name.downcase
end
end
end

context 'with separator option' do
let(:options) { default_options.merge({ separator: 'x' }) }
let(:branch_name) { 'TICKETx12345xTicketxDescription' }

it_behaves_like 'it formats the branch name properly'
end

context 'with format_string option' do
let(:options) { default_options.merge({ format_string: '%d %t' }) }
let(:branch_name) { 'Ticket_Description_TICKET_12345' }

it_behaves_like 'it formats the branch name properly'

context 'when the %t format placeholder is missing' do
let(:options) { default_options.merge({ format_string: '%d' }) }
let(:branch_name) { 'Ticket_Description' }

it_behaves_like 'the format_string is invalid'
end

context 'when the %d format placeholder is missing' do
let(:options) { default_options.merge({ format_string: '%t' }) }
let(:branch_name) { 'TICKET_12345' }

it_behaves_like 'the format_string is invalid'
end

context 'when the %t and %d format placeholders are missing' do
let(:options) { default_options.merge({ format_string: '12345' }) }
let(:branch_name) { 'Ticket_Description_TICKET_12345' }

it_behaves_like 'the format_string is invalid'
end
end
end
end
3 changes: 2 additions & 1 deletion spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true

require 'pry-byebug'
require 'thor'

require 'branch/name'
require 'branch/name/clipable'
Expand All @@ -12,7 +13,7 @@
require 'branch/name/projectable'
require 'branch/name/version'

Dir[File.join(Dir.pwd, "spec/support/**/*.rb")].each {|f| require f}
Dir[File.join(Dir.pwd, 'spec/support/**/*.rb')].each { |f| require f }

RSpec.configure do |config|
# Enable flags like --only-failures and --next-failure
Expand Down
18 changes: 0 additions & 18 deletions spec/support/shared_contexts/test_objects.rb

This file was deleted.

0 comments on commit 55b3c91

Please sign in to comment.