pgit 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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