pgit 0.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a72ba79fbaa4bfba38e13548cff4ac44812fb0b1
4
+ data.tar.gz: fd94693b8ff782640064f0a134d822b4922ab4bd
5
+ SHA512:
6
+ metadata.gz: 5491115049d8c35b86df684a793be62ad71a7b3678379a3eb5337be7692c7e67903cd3a088cd0b729c419473db5a0a6d69031ec5386426de3a4e9f0a3cb3de75
7
+ data.tar.gz: ea5e67ecc7a8ca90e475ec261fec625581b6bbe92bd337d25631f345df57d8efee6dead19f0a49ca9db735da4569d4e152797513b5b1a0c29860feb0d6372d7a
@@ -0,0 +1 @@
1
+ *.un~
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color -fd
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+ gem 'pry'
3
+ gemspec
@@ -0,0 +1,26 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ pgit (0.0.2)
5
+ gli (= 2.12.2)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ coderay (1.1.0)
11
+ gli (2.12.2)
12
+ method_source (0.8.2)
13
+ pry (0.10.1)
14
+ coderay (~> 1.1.0)
15
+ method_source (~> 0.8.1)
16
+ slop (~> 3.4)
17
+ rake (10.4.2)
18
+ slop (3.6.0)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ pgit!
25
+ pry
26
+ rake
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Edderic
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,32 @@
1
+ # PGit
2
+
3
+ ## Example Usage
4
+
5
+ Assuming that:
6
+ - you have a project that uses Pivotal Tracker and Git that is listed under ~/.pgit.rc.yml
7
+ - your working directory is in that project,
8
+ - you want to automatically branch out based on the story title
9
+ - the story title with story id 10102004 is "Implement a really cool feature"
10
+
11
+ ```
12
+ $ pgit story_branch -s 10102004
13
+ ```
14
+
15
+ will create a branch for you named `implement-really-cool-feature-10102004`
16
+
17
+ ## Installation
18
+
19
+ 1. Install via RubyGems:
20
+
21
+ ```
22
+ $ gem install pgit
23
+ ```
24
+
25
+ 2. Setup configuration file:
26
+
27
+ ```
28
+ $ pgit install
29
+ ```
30
+
31
+ This will generate a YAML file under `~/.pgit.rc.yml`. Edit that file to add information about projects that you're working on. Each project needs a project `id`, Pivotal Tracker `api_token`, and `path`
32
+
@@ -0,0 +1,24 @@
1
+ require 'rake/clean'
2
+ require 'rubygems'
3
+ require 'rubygems/package_task'
4
+ require 'rdoc/task'
5
+
6
+ Rake::RDocTask.new do |rd|
7
+ rd.main = "README.rdoc"
8
+ rd.rdoc_files.include("README.rdoc","lib/**/*.rb","bin/**/*")
9
+ rd.title = 'PGit'
10
+ end
11
+
12
+ spec = eval(File.read('pgit.gemspec'))
13
+
14
+ Gem::PackageTask.new(spec) do |pkg|
15
+ end
16
+
17
+ desc 'Run specs'
18
+ require 'rake/testtask'
19
+ Rake::TestTask.new(:spec) do |s|
20
+ s.libs << "spec"
21
+ s.test_files = FileList['spec/**/*_test.rb']
22
+ end
23
+
24
+ task :default => [:spec]
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env ruby
2
+ require 'gli'
3
+ require 'pgit'
4
+ include GLI::App
5
+
6
+ program_desc 'Optimize your Pivotal Tracker and Git workflow'
7
+
8
+ version Pgit::VERSION
9
+
10
+ subcommand_option_handling :normal
11
+ arguments :strict
12
+
13
+ # desc 'Path to the config file'
14
+ # default_value "#{ENV['HOME']}/.pgit.rc.yml"
15
+ # arg_name '/path/to/.pivotal.yml'
16
+ # flag [:c,:config]
17
+
18
+ # desc 'Bypasses the app asking for confirmation'
19
+ # switch [:force]
20
+
21
+ # desc 'PivotalTracker API Token'
22
+ # arg_name 'secr3tT0ken123'
23
+ # flag [:'api-token']
24
+
25
+ desc "Installs the pgit configuration file"
26
+ command :install do |c|
27
+ c.action do |global_options,options,args|
28
+ PGit::Installer.new(global_options, options, args)
29
+ end
30
+ end
31
+
32
+ # desc 'Start, finish, etc. Pivotal Tracker story branches'
33
+ desc 'Start Pivotal Tracker story branches'
34
+ long_desc "Makes a cURL request to Pivotal Tracker to fetch the story, based
35
+ on the given story id, parses the title, appends it with the story id. It then
36
+ creates a branch name with that parsed title and does a `git checkout` to it. "
37
+
38
+ command :story_branch do |c|
39
+ c.desc "Parses the title of the given Pivotal Tracker story,\n" +
40
+ " makes the branch name, and does a checkout"
41
+ c.arg_name 'STORY_ID'
42
+ c.flag :s, :start
43
+
44
+ # c.desc "Merge back to staging, remove local and remote (origin?) branches"
45
+ # c.switch :f, :finish
46
+
47
+ # c.desc "Attempts to join the story-branch that, presumably, already exists"
48
+ # c.arg_name 'STORY_ID'
49
+ # c.flag :j, :join
50
+
51
+ c.action do |global_options,options,args|
52
+ PGit::StoryBranch::Application.new(global_options, options, args)
53
+ end
54
+ end
55
+
56
+ # desc 'Wraps `git commit -m` and prepends the message with story id of the branch'
57
+
58
+ # command :commit do |c|
59
+ # arg_name 'Describe arguments to commit here'
60
+ # c.action do |global_options,options,args|
61
+ # puts "commit command ran"
62
+ # end
63
+ # end
64
+
65
+
66
+ desc 'Initializes configuration file'
67
+
68
+ arg_name 'path/to/config_file'
69
+
70
+ # command :init_config do |c|
71
+ # c.action do |global_options,options,args|
72
+ # puts "init_config command ran"
73
+ # end
74
+ # end
75
+
76
+ pre do |global,command,options,args|
77
+ # Pre logic here
78
+ # Return true to proceed; false to abort and not call the
79
+ # chosen command
80
+ # Use skips_pre before a command to skip this block
81
+ # on that command only
82
+ true
83
+ end
84
+
85
+ post do |global,command,options,args|
86
+ # Post logic here
87
+ # Use skips_post before a command to skip this
88
+ # block on that command only
89
+ end
90
+
91
+ on_error do |exception|
92
+ # Error logic here
93
+ # return false to skip default error handling
94
+ true
95
+ end
96
+
97
+ exit run(ARGV)
@@ -0,0 +1,14 @@
1
+ require 'json'
2
+ require 'pgit/configuration'
3
+ require 'pgit/current_branch'
4
+ require 'pgit/current_project'
5
+ require 'pgit/installer'
6
+ require 'pgit/name_parser'
7
+ require 'pgit/story'
8
+ require 'pgit/story_branch'
9
+ require 'pgit/story_branch/application'
10
+ require 'pgit/version.rb'
11
+ require 'yaml'
12
+
13
+ # Add requires for other files you add to your project here, so
14
+ # you just need to require this one file in your bin file
@@ -0,0 +1,77 @@
1
+ #
2
+ # Loads the Pivotal-Git configuration file
3
+ #
4
+ # - config_path is the path to the pivotal-git configuration file
5
+ # This loads the file. Throws an error if a key (such as api_token, path, id)
6
+ # is missing. Check #general_error_message for more info
7
+ #
8
+
9
+ module PGit
10
+ class Configuration
11
+ def self.default_options
12
+ {
13
+ 'projects' => [
14
+ {
15
+ 'api_token' => 'somepivotalatoken124',
16
+ 'id' => '12345',
17
+ "path" => "~/some/path/to/a/pivotal-git/project"
18
+ },
19
+ {
20
+ 'api_token' => 'somepivotalatoken124',
21
+ 'id' => '23429070',
22
+ "path" => "~/some/other/pivotal-git/project"
23
+ }
24
+ ]
25
+ }
26
+ end
27
+
28
+ def initialize(config_path = '~/.pgit.rc.yml')
29
+ @expanded_path = File.expand_path(config_path)
30
+ if File.exists? @expanded_path
31
+ config_file = File.open(@expanded_path, 'r')
32
+ @yaml = YAML.load(config_file)
33
+
34
+ validate_existence_of_at_least_one_project
35
+ validate_presence_of_items_in_each_project
36
+ else
37
+ raise missing_config_default
38
+ end
39
+ end
40
+
41
+ def to_yaml
42
+ @yaml
43
+ end
44
+
45
+ private
46
+
47
+ def missing_config_default
48
+ "Default configuration file does not exist. Please run `pgit install`"
49
+ end
50
+
51
+ def general_error_message
52
+ "Please have the following layout:\n" + YAML.dump(PGit::Configuration.default_options)
53
+ end
54
+
55
+ def validate_presence_of_items_in_each_project
56
+ projects = @yaml["projects"]
57
+ all_present = projects.all? do |project|
58
+ project["api_token"] &&
59
+ project["path"] &&
60
+ project["id"]
61
+ end
62
+
63
+ unless all_present
64
+ raise "Error: Must have a path, id, and api_token for each project.\n" +
65
+ general_error_message
66
+ end
67
+ end
68
+
69
+ def validate_existence_of_at_least_one_project
70
+ unless @yaml["projects"]
71
+ raise "Error: #{@expanded_path} needs at least one project.\n" +
72
+ general_error_message
73
+
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,23 @@
1
+ module PGit
2
+ class CurrentBranch
3
+ def initialize
4
+ @branches = `git branch`
5
+
6
+ raise @branches unless current.any?
7
+ end
8
+
9
+ def name
10
+ current.first.gsub(/\*\s*/, '')
11
+ end
12
+
13
+ def story_id
14
+ name.scan(/\d+$/).first
15
+ end
16
+
17
+ private
18
+
19
+ def current
20
+ @branches.scan(/\*.+/)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,62 @@
1
+ #
2
+ # Decides what the "current project" is, in relation to the pwd.
3
+ #
4
+ # - config_yaml: has the project configurations. It has at least one
5
+ # project. Each project has an (pivotal) api_token, path, and (pivotal)
6
+ # id
7
+ #
8
+
9
+ module PGit
10
+ class CurrentProject
11
+ def initialize(config_yaml)
12
+ @current_project = find_current_project(config_yaml)
13
+ end
14
+
15
+ def pwd
16
+ project_path = @current_project["path"]
17
+ File.expand_path(project_path, __FILE__)
18
+ end
19
+
20
+ def id
21
+ @current_project["id"]
22
+ end
23
+
24
+ def api_token
25
+ @current_project["api_token"]
26
+ end
27
+
28
+ private
29
+
30
+ def validate_pwd_match_at_least_one(matching_projects)
31
+ if matching_projects.length == 0
32
+ raise "None of the project paths matches the working directory"
33
+ end
34
+ end
35
+
36
+ def escape_slashes(project_path)
37
+ project_path.gsub('/','\/')
38
+ end
39
+
40
+ def find_matching_projects(projects)
41
+ projects.select do |project|
42
+ project_path = project["path"]
43
+ extended_path = File.expand_path(project_path, __FILE__)
44
+ escaped_project = escape_slashes(extended_path)
45
+ Dir.pwd.match(/#{escaped_project}/)
46
+ end
47
+ end
48
+
49
+ def find_current_project(config_yaml)
50
+ projects = config_yaml["projects"]
51
+ matching_projects = find_matching_projects(projects)
52
+
53
+ validate_pwd_match_at_least_one(matching_projects)
54
+ find_best_match(matching_projects)
55
+ end
56
+
57
+ def find_best_match(matching_projects)
58
+ matching_projects.sort! { |a,b| b["path"].length <=> a["path"].length }
59
+ matching_projects.first
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,32 @@
1
+ module PGit
2
+ class Installer
3
+ def initialize(glob_opts, opts, args)
4
+ file_path = "~/.pgit.rc.yml"
5
+ @expanded_path = File.expand_path(file_path)
6
+
7
+ if File.exists? @expanded_path
8
+ raise "Error: #{file_path} already exists"
9
+ else
10
+ ask_continue
11
+ end
12
+ end
13
+
14
+ def ask_continue
15
+ puts "*** Installing example pgit configuration file under ~/.pgit.rc.yml. Continue? [Y/n]"
16
+ if STDIN.gets.chomp.match(/y/i)
17
+ puts "Saving example pgit config in ~/.pgit.rc.yml..."
18
+ write_example_pgit_rc_file
19
+ else
20
+ puts "Aborting installation..."
21
+ end
22
+ end
23
+
24
+ def write_example_pgit_rc_file
25
+ File.open(@expanded_path, 'w') do |f|
26
+ YAML.dump(PGit::Configuration.default_options, f)
27
+ end
28
+
29
+ puts "Saved! Please edit ~/.pgit.rc.yml and add the proper Pivotal Tracker API tokens, id, and file paths for each project"
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,57 @@
1
+ #
2
+ # Parses pivotal story titles and turns them into git branch names
3
+ # - story.name: title of the pivotal tracker story
4
+ #
5
+ # - story_id: id of the pivotal tracker story
6
+ #
7
+ # ex: Fly so high in the sky 12345 becomes fly-so-high-sky-12345
8
+ module PGit
9
+ class StoryBranch
10
+ class NameParser
11
+ def initialize(story)
12
+ @story = story
13
+ @story_name = story.name
14
+ end
15
+
16
+ def story_id
17
+ @story.id
18
+ end
19
+
20
+ def name
21
+ remove_fluff_words
22
+ remove_non_alphanumeric_characters
23
+ downcase
24
+ add_story_id
25
+ end
26
+
27
+ private
28
+
29
+ def remove_non_alphanumeric_characters
30
+ words = @story_name.split(' ')
31
+ split_words = words.each { |word| word.gsub!(/\W/, '') }
32
+ @story_name = split_words.select do |word|
33
+ !word.empty?
34
+ end.join('-')
35
+ end
36
+
37
+ def remove_fluff_words
38
+ fluff_words = %w{the on of}
39
+ fluff_words.each { |fluff_word| @story_name.gsub!(/\b#{fluff_word}\b/i, '') }
40
+ remove_extraneous_white_spaces
41
+ end
42
+
43
+ def remove_extraneous_white_spaces
44
+ @story_name.strip!
45
+ @story_name.gsub!(/\s+/, ' ')
46
+ end
47
+
48
+ def downcase
49
+ @story_name.downcase!
50
+ end
51
+
52
+ def add_story_id
53
+ "#{@story_name}-#{story_id}"
54
+ end
55
+ end
56
+ end
57
+ end