Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Miscellaneous changes #6

Merged
merged 1 commit into from
Sep 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.