git-daily 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in git-daily.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,31 @@
1
+ The BSD License
2
+
3
+ Copyright (c) 2012, Koichiro Ohba
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are
8
+ met:
9
+
10
+ * Redistributions of source code must retain the above copyright
11
+ notice, this list of conditions and the following disclaimer.
12
+
13
+ * Redistributions in binary form must reproduce the above copyright
14
+ notice, this list of conditions and the following disclaimer in the
15
+ documentation and/or other materials provided with the distribution.
16
+
17
+ * Neither the name of the author nor the names of its
18
+ contributors may be used to endorse or promote products derived from
19
+ this software without specific prior written permission.
20
+
21
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.rst ADDED
@@ -0,0 +1,137 @@
1
+ git-daily
2
+ ===========================
3
+
4
+ "git-daily" is a tool which helps you to do daily workflow easier.
5
+
6
+ Sub-commands are::
7
+
8
+ git daily init
9
+ git daily config
10
+ git daily push
11
+ git daily pull
12
+ git daily release open
13
+ git daily release list
14
+ git daily release sync
15
+ git daily release close
16
+ git daily hotfix open
17
+ git daily hotfix list
18
+ git daily hotfix sync
19
+ git daily hotfix close
20
+ git daily version
21
+ git daily help
22
+
23
+
24
+ Requirements
25
+ --------------------------
26
+
27
+ * Git: >= 1.7.0
28
+ * Ruby: >= 1.8.3
29
+
30
+
31
+ Installation
32
+ --------------------------
33
+
34
+ Install from openpear.org ::
35
+
36
+ gem instasll git-daily
37
+
38
+ Install develop version ::
39
+
40
+ cd /path/to/dir
41
+ git clone git://github.com/koichiro/git-daily.git
42
+ rake build
43
+ gem install pkg/git-daily-X.X.X.gem
44
+
45
+ Cheat Sheet
46
+ --------------------------
47
+
48
+ Initialization
49
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^
50
+
51
+ To initialize, use ::
52
+
53
+ git daily init
54
+
55
+
56
+ Configuration
57
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^
58
+
59
+ * To show configuration for git-daliy use ::
60
+
61
+ git daily config
62
+
63
+ * To set the configuration use ::
64
+
65
+ git daily config [<key>] [<value>]
66
+
67
+ Release
68
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^
69
+
70
+ * To open the release process of the day, use ::
71
+
72
+ git daily release open
73
+
74
+ * To sync opened or closed daily release process, use ::
75
+
76
+ git daily release sync
77
+
78
+ * To show the release list, use::
79
+
80
+ git daily release list
81
+
82
+ * When gitdaily.logurl is defined, git-daily shows author lists
83
+ with logurl. git-daily replaces %s in gitdaily.logurl to a commit id. ::
84
+
85
+ [config]
86
+ gitdaily.logurl = "http://github.com/user/git-daily/commit/%s"
87
+
88
+ [output]
89
+ @userA:
90
+ http://github.com/user/git-daily/commit/0123456789.....
91
+ ...
92
+
93
+ * To close daily release process, use ::
94
+
95
+ git daily release close
96
+
97
+ Hotfix
98
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^
99
+
100
+ * To open the hotfix process of the day, use ::
101
+
102
+ git daily hotfix open
103
+
104
+ * To sync opened or closed hotfix process, use ::
105
+
106
+ git daily hotfix sync
107
+
108
+ * To show the release list, use::
109
+
110
+ git daily hotfix list
111
+
112
+ * To close hotfix process, use ::
113
+
114
+ git daily hotfix close
115
+
116
+
117
+ Contribution
118
+ -------------
119
+
120
+ Use `gitFlow <https://github.com/nvie/gitflow>`_ to develop git-daily.
121
+ When you want to fix some bugs or implemente some new features,
122
+ commit not to ``master`` branch but to ``develop`` branch.
123
+
124
+
125
+ Test
126
+ ^^^^^^
127
+
128
+ $ rake test
129
+
130
+
131
+ Links
132
+ -------
133
+
134
+ References here (Japanese Only).
135
+
136
+ * http://speakerdeck.com/u/sotarok/p/git-daily-a-tool-supports-a-daily-workflow-with-remote
137
+ * http://d.hatena.ne.jp/sotarok/20111015/pyfes_git_daily
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # -*- coding: utf-8; mode: ruby -*-
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.libs << "test"
8
+ t.test_files = FileList['test/test*.rb']
9
+ t.verbose = true
10
+ end
data/bin/git-daily ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ self_file =
5
+ if File.symlink?(__FILE__)
6
+ require 'pathname'
7
+ Pathname.new(__FILE__).realpath
8
+ else
9
+ __FILE__
10
+ end
11
+ $:.unshift(File.dirname(self_file) + "/../lib")
12
+
13
+ begin
14
+ require 'rubygems'
15
+ gem 'git-daily'
16
+ rescue LoadError
17
+ end
18
+
19
+ require 'git-daily'
20
+
21
+ Git::Daily.application.run
data/git-daily.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8; mode: ruby -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "git-daily/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "git-daily"
7
+ s.version = Git::Daily::VERSION
8
+ s.authors = ["Koichiro Ohba"]
9
+ s.email = ["koichiro@meadowy.org"]
10
+ s.homepage = "https://github.com/koichiro/git-daily"
11
+ s.summary = %q{git-daily on ruby is a tool which helps you to do daily workflow easier on Git.}
12
+ s.description = %q{git-daily on Ruby is a tool which helps you to do daily workflow easier on Git. This is the Ruby version. The original PHP version is here: https://github.com/sotarok/git-daily}
13
+
14
+ s.rubyforge_project = "git-daily"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ # s.add_development_dependency "rspec"
23
+ # s.add_runtime_dependency "rest-client"
24
+ end
@@ -0,0 +1,74 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Git
4
+ module Daily
5
+ class Application
6
+
7
+ attr_reader :original_dir
8
+ attr_reader :options
9
+ attr_reader :commands
10
+ attr_accessor :remote
11
+
12
+ def initialize
13
+ @original_dir = Dir.pwd
14
+ @commands = {}
15
+ end
16
+
17
+ def options
18
+ @options ||= OpenStruct.new
19
+ end
20
+
21
+ def handle_options
22
+ command = ARGV.shift
23
+ if @commands.has_key?(command)
24
+ @commands[command].run
25
+ else
26
+ $stderr.puts @commands["help"].usage
27
+ exit
28
+ end
29
+ end
30
+
31
+ def run
32
+ #exception_handling do
33
+ init
34
+ #end
35
+ end
36
+
37
+ def init
38
+ #exception_handling do
39
+ load_commands
40
+ handle_options
41
+ #end
42
+ end
43
+
44
+ def load_commands
45
+ Dir[File.join(File.dirname(__FILE__), "command", "*.rb")].each do |file|
46
+ load file
47
+ name = File.basename(file, ".rb")
48
+ @commands[name] = Git::Daily.const_get(name.capitalize).new
49
+ end
50
+ end
51
+
52
+ def exception_handling
53
+ begin
54
+ yield
55
+ rescue SystemExit => ex
56
+ raise
57
+ rescue OptionParser::InvalidOption => ex
58
+ $stderr.puts ex.message
59
+ rescue Exception => ex
60
+ display_error_message(ex)
61
+ exit(false)
62
+ end
63
+ end
64
+
65
+ def display_error_message(ex)
66
+ $stderr.puts "git-daily aborted!"
67
+ $stderr.puts ex.message
68
+ if options.trace
69
+ $stderr.puts ex.backtrace.join("\n")
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,90 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Git
4
+ module Daily
5
+ class Config < Command
6
+
7
+ SUBCOMMAND = {
8
+ "remote" => lambda {
9
+ r = remotes
10
+ r.map! {|url| url[/^remote\.([^\.]+)\.url=(.*)/, 1] }
11
+ selected_url = ARGV.shift
12
+ if r.find {|v| v == selected_url }
13
+ `git config gitdaily.remote #{selected_url}`
14
+ puts "Your remote is [#{selected_url}]"
15
+ else
16
+ raise "no such remote url: #{selected_url}"
17
+ end
18
+ },
19
+ "develop" => lambda {
20
+ b = branches
21
+ input = ARGV.shift
22
+ if b.find { |v| v == input }
23
+ `git config gitdaily.develop #{input}`
24
+ puts "Your development branch is [#{input}]"
25
+ else
26
+ raise "no such branch: #{input}"
27
+ end
28
+ },
29
+ "master" => lambda {
30
+ b = branches
31
+ input = ARGV.shift
32
+ if b.find { |v| v == input }
33
+ `git config gitdaily.master #{input}`
34
+ puts "Your master branch is [#{input}]"
35
+ else
36
+ raise "no such branch: #{input}"
37
+ end
38
+ },
39
+ "logurl" => lambda {
40
+ url = ARGV.shift
41
+ `git config gitdaily.logurl #{url}`
42
+ puts "Your log url is [#{url}]"
43
+ }
44
+ }
45
+
46
+ def help
47
+ "config\tSet or show config"
48
+ end
49
+
50
+ def run
51
+ subcommand = ARGV.shift
52
+ if SUBCOMMAND.has_key?(subcommand)
53
+ return SUBCOMMAND[subcommand].call
54
+ end
55
+
56
+ # show config
57
+ r = `git config --list`.split(/\n/).select {|a| a[/^gitdaily/] }
58
+ if r.empty?
59
+ raise "git-daily: not initialized. please run: git daily init"
60
+ else
61
+ r.each do |s|
62
+ puts s
63
+ end
64
+ end
65
+ r
66
+ end
67
+
68
+ def usage
69
+ <<-EOS
70
+ Usage: git daily config remote origin
71
+
72
+ Example:
73
+
74
+ Remote name :
75
+ git daily config remote origin
76
+
77
+ Branch name of develop :
78
+ git daily config develop develop
79
+
80
+ Branch name of master :
81
+ git daily config master master
82
+
83
+ URL template for dump list (will dump commit hash instead of "%s") :
84
+ GitWeb : git daily config logurl "http://example.com/?p=repositories/example.git;a=commit;h=%s"
85
+ GitHub : git daily config logurl "https://github.com/sotarok/git-daily/commit/%s"
86
+ EOS
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,34 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Git
4
+ module Daily
5
+ class Help < Command
6
+
7
+ def help
8
+ "help\tShow help (run \"help {subcommand}\" to get more help)"
9
+ end
10
+
11
+ def run
12
+ subcommand = ARGV.shift
13
+ if Git::Daily.application.commands.has_key?(subcommand)
14
+ $stderr.puts Git::Daily.application.commands[subcommand].usage
15
+ else
16
+ $stderr.puts usage
17
+ end
18
+ end
19
+
20
+ def usage
21
+ r = <<-EOS
22
+ git-daily: command [options]
23
+
24
+ Usage:
25
+
26
+ EOS
27
+ Git::Daily.application.commands.keys.sort.each do |key|
28
+ r += " #{Git::Daily.application.commands[key].help}\n"
29
+ end
30
+ r += "\n"
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,38 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require "git-daily/command/release"
4
+
5
+ module Git
6
+ module Daily
7
+ class Hotfix < Release
8
+
9
+ def initialize
10
+ @base_branch = "master"
11
+ @merge_to = ["master", "develop", "release"]
12
+ @branch_prefix = 'hotfix'
13
+ end
14
+
15
+ def help
16
+ "hotfix\tOperation hotfix release"
17
+ end
18
+
19
+ def merge_branches
20
+ rel_branches = Command.release_branches("release")
21
+ if rel_branches.empty?
22
+ return ["master", "develop"]
23
+ else
24
+ return ["master", "release"]
25
+ end
26
+ end
27
+
28
+ def usage
29
+ <<-EOS
30
+ Usage: git daily hotfix open : Open hotfix-release process
31
+ or: git daily hotfix list : Show hotfix list
32
+ or: git daily hotfix sync : Sync current opened hotfix process
33
+ or: git daily hotfix close : Close to hotfix-release process
34
+ EOS
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,92 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require "git-daily/command"
4
+
5
+ module Git
6
+ module Daily
7
+ class Init < Command
8
+
9
+ def option
10
+ OptionParser.new
11
+ end
12
+
13
+ def help
14
+ "init\tInitialize git daily"
15
+ end
16
+
17
+ def run
18
+ r = `git config --bool gitdaily.init`
19
+ if r.chomp == "true"
20
+ # initialized repo
21
+ return nil
22
+ end
23
+ remotes = `git config --list`.split(/\n/).select {|a| a[/^remote\.([^\.]+)\.url/] }
24
+ if remotes.empty?
25
+ raise "don't have remote repojitory"
26
+ end
27
+
28
+ remotes.map! {|r| r[/^remote\.([^\.]+)\.url=(.*)/, 1] }
29
+
30
+ selected_url = nil
31
+ if remotes.size >= 2
32
+ puts "Choose your remote url:"
33
+ i = 0
34
+ remotes.each do |v|
35
+ puts " #{i}: #{v}"
36
+ i += 1
37
+ end
38
+ print " > "
39
+ n = gets.to_i
40
+ selected_url = remotes[n]
41
+ else
42
+ selected_url = remotes[0]
43
+ end
44
+
45
+ r = `git config gitdaily.remote #{selected_url}`
46
+ puts "Your remote is [#{selected_url}]"
47
+ Git::Daily.application.remote = selected_url
48
+
49
+ # master branch
50
+ print "Name master branch [master]: "
51
+ master = gets.strip
52
+ if master.empty?
53
+ master = "master"
54
+ end
55
+ `git config gitdaily.master #{master}`
56
+
57
+ # develop branch
58
+ print "Name develop branch [develop]: "
59
+ develop = gets.strip
60
+ if develop.empty?
61
+ develop = "develop"
62
+ end
63
+ `git config gitdaily.develop #{develop}`
64
+
65
+ unless Command.has_branch? develop
66
+ remote = Command.remote
67
+ if remote and Command.has_remote_branch?(remote, develop)
68
+ `git checkout #{develop}`
69
+ else
70
+ `git checkout -b #{develop}`
71
+ if remote
72
+ `git push #{remote} #{develop}`
73
+ end
74
+ end
75
+ end
76
+
77
+ # initialized
78
+ `git config gitdaily.init true`
79
+
80
+ puts
81
+ puts "git-daily completed to initialize."
82
+ selected_url
83
+ end
84
+
85
+ def usage
86
+ <<-EOS
87
+ Usage: git daily init
88
+ EOS
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,51 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Git
4
+ module Daily
5
+ class Pull < Command
6
+
7
+ def help
8
+ "pull\tPull remote to local (for only same branch)"
9
+ end
10
+
11
+ def run
12
+ remote = Command.remote
13
+ if remote.empty?
14
+ raise "no remote setting"
15
+ end
16
+
17
+ current_branch = Command.current_branch
18
+ unless current_branch
19
+ raise "not on any branches"
20
+ end
21
+
22
+ remote_branch = Command.remote_branch(remote, current_branch)
23
+ unless remote_branch
24
+ raise "note remote branch named: #{current_branch}"
25
+ end
26
+
27
+ rebase = false
28
+ OptionParser.new do |opt|
29
+ opt.on('--rebase') { |v| rebase = true }
30
+ opt.parse!(ARGV)
31
+ end
32
+
33
+ puts "run git pull #{remote} #{current_branch}#{ rebase ? ' (rebase)' : ''}"
34
+ r = `git pull #{rebase ? '--rebase' : ''} #{remote} #{current_branch}`
35
+ puts r
36
+ unless $?.success?
37
+ $stderr.puts "git pull failed:"
38
+ raise "git pull failed"
39
+ end
40
+ puts "pull completed"
41
+ end
42
+
43
+ def usage
44
+ <<-EOS
45
+ Usage: git daily pull
46
+ or: git daily pull --rebase
47
+ EOS
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,44 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Git
4
+ module Daily
5
+ class Push < Command
6
+
7
+ def help
8
+ "push\tPush local to remote (for only same branch)"
9
+ end
10
+
11
+ def run
12
+ remote = Command.remote
13
+ if remote.empty?
14
+ raise "no remote setting"
15
+ end
16
+
17
+ current_branch = Command.current_branch
18
+ unless current_branch
19
+ raise "not on any branches"
20
+ end
21
+
22
+ remote_branch = Command.remote_branch(remote, current_branch)
23
+ unless remote_branch
24
+ raise "note remote branch named: #{current_branch}"
25
+ end
26
+
27
+ puts "run git push #{remote} #{current_branch}"
28
+ r = `git push #{remote} #{current_branch}`
29
+ puts r
30
+ unless $?.success?
31
+ $stderr.puts "git push failed:"
32
+ raise "git push failed"
33
+ end
34
+ puts "push completed"
35
+ end
36
+
37
+ def usage
38
+ <<-EOS
39
+ Usage: git daily push
40
+ EOS
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,384 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'date'
4
+
5
+ module Git
6
+ module Daily
7
+ class Release < Command
8
+
9
+ SUBCOMMAND = {
10
+ "open" => :open,
11
+ "list" => :list,
12
+ "sync" => :sync,
13
+ "close" => :close
14
+ } unless const_defined? :SUBCOMMAND
15
+
16
+ def initialize
17
+ @base_branch = "develop"
18
+ @branch_prefix = "release"
19
+ @merge_to = ["master", "develop"]
20
+ end
21
+
22
+ def help
23
+ "release\tOperation daily release"
24
+ end
25
+
26
+ def run
27
+ unless Command.clean?
28
+ raise "git status is not clean"
29
+ end
30
+
31
+ subcommand = ARGV.shift
32
+ if SUBCOMMAND.has_key?(subcommand)
33
+ return send(SUBCOMMAND[subcommand])
34
+ else
35
+ $stderr.puts "please specify release subcommand"
36
+ $stderr.puts usage
37
+ exit 1
38
+ end
39
+ end
40
+
41
+ def open
42
+ cur_branch = Command.current_branch
43
+ base_branch = @base_branch
44
+ if cur_branch != base_branch
45
+ raise "currently not on #{base_branch} but on #{cur_branch}"
46
+ end
47
+
48
+ rel_branches = Command.release_branches(@branch_prefix)
49
+ unless rel_branches.empty?
50
+ raise "release process (on local) is not closed, so cannot open relase\n release branches: #{rel_branches.join(',')}"
51
+ end
52
+
53
+ remote = Command.remote
54
+ if remote
55
+ puts "first, fetch remotes"
56
+ `git fetch --all`
57
+
58
+ rels = `git branch -a --no-color`.split(/\n/).select { |b| b[/remotes\/#{remote}\/#{@branch_prefix}/]}
59
+ unless rels.empty?
60
+ raise "relase process (on local) is not closed, so cannot open releas\n relase branchs: #{rels.join(',')}"
61
+ end
62
+ end
63
+
64
+ new_release_branch = "#{@branch_prefix}/#{DateTime.now.strftime("%Y%m%d-%H%M")}"
65
+ puts "Confirm: create branch #{new_release_branch} from #{cur_branch} ?"
66
+ print " [yN] : "
67
+ confirm = $stdin.gets
68
+ unless confirm.strip[/^[Yy]/]
69
+ raise "abort"
70
+ end
71
+
72
+ # merge current branch
73
+ if remote
74
+ puts "merge #{cur_branch} branch from remote"
75
+ r = `git merge #{remote}/#{cur_branch}`
76
+ unless $? == 0
77
+ $stderr.puts "merge failed"
78
+ $stderr.puts r
79
+ raise "abort"
80
+ end
81
+ end
82
+
83
+ # create release branch
84
+ puts "create release branch: #{new_release_branch}"
85
+ r = `git branch #{new_release_branch}`
86
+ if remote
87
+ puts "push to remote: #{remote}"
88
+ r = `git push #{remote} #{new_release_branch}`
89
+ puts r
90
+ unless $? == 0
91
+ $stderr.puts "push failed"
92
+ r = `git branch -d #{new_release_branch}`
93
+ $stderr.puts r
94
+ $stderr.puts "rollback (delete branch)"
95
+ end
96
+ end
97
+
98
+ `git checkout #{new_release_branch}`
99
+ puts "release opened"
100
+ end
101
+
102
+ def merge_branches
103
+ @merge_to
104
+ end
105
+
106
+ def close
107
+ rel_branches = Command.release_branches(@branch_prefix)
108
+ if rel_branches.empty?
109
+ raise "#{@branch_prefix} branch not found. abort."
110
+ end
111
+ rel_branch = rel_branches.shift
112
+ remote = Command.remote
113
+
114
+ merge_branches.each do |branch_name|
115
+
116
+ branches = `git branch`.split("\n").select{|v| v[/#{branch_name}/]}
117
+ merge_branch = branches[0][/^\*/] ? branches[0][2 .. -1] : branches[0].strip
118
+ next unless merge_branch
119
+
120
+ if remote
121
+ puts "first, fetch remotes"
122
+ `git fetch --all`
123
+ puts "diff check"
124
+
125
+ diff_branch1 = "#{rel_branch}..#{remote}/#{rel_branch}"
126
+ diff_branch2 = "#{remote}/#{rel_branch}..#{rel_branch}"
127
+ diff1 = `git diff #{diff_branch1}`
128
+ diff2 = `git diff #{diff_branch2}`
129
+ unless diff1.empty? or diff1.empty?
130
+ $stderr.puts "There are some diff between local and $remote, run release sync first."
131
+ raise "abort"
132
+ end
133
+ end
134
+
135
+ $stderr.puts "checkout #{merge_branch} and merge #{rel_branch} to #{merge_branch}"
136
+ `git checkout #{merge_branch}`
137
+ if remote
138
+ r = `git daily pull`
139
+ puts r
140
+ unless $? == 0
141
+ $stderr.puts "pull failed"
142
+ raise "abort"
143
+ end
144
+ end
145
+
146
+ merged_branches = Command.merged_branches
147
+ unless merged_branches.find {|v| v == rel_branch}
148
+ r = `git merge --no-ff #{rel_branch}`
149
+ puts r
150
+ unless $? == 0
151
+ $stderr.puts "merge failed"
152
+ raise "abort"
153
+ end
154
+ end
155
+
156
+ puts "push #{merge_branch} to #{remote}"
157
+ `git checkout #{merge_branch}`
158
+ r = `git push #{remote} #{merge_branch}`
159
+ puts r
160
+ unless $? == 0
161
+ $stderr.puts "push failed"
162
+ raise "abort"
163
+ end
164
+ end
165
+
166
+ puts "delete branch: #{rel_branch}"
167
+ r = `git branch -d #{rel_branch}`
168
+ puts r
169
+ unless $? == 0
170
+ $stderr.puts "failed to delete local #{rel_branch}"
171
+ raise "abort"
172
+ end
173
+ if remote
174
+ r = `git push #{remote} :#{rel_branch}`
175
+ puts r
176
+ unless $? == 0
177
+ $stderr.puts "failed to delete #{remote}'s #{rel_branch}"
178
+ raise "abort"
179
+ end
180
+ end
181
+
182
+ base = @base_branch
183
+ `git checkout #{base}`
184
+ puts "#{@branch_prefix} closed"
185
+
186
+ end
187
+
188
+ # Sync release
189
+ def sync
190
+ remote = Command.remote
191
+ unless remote
192
+ raise "remote not found. abort."
193
+ end
194
+ cur = Command.current_branch
195
+ develop = Command.develop
196
+
197
+ puts "first, fetch remotes"
198
+ `git fetch --all`
199
+ puts "cleanup remote"
200
+ `git remote prune #{remote}`
201
+
202
+ rel = nil
203
+ rel_branches = Command.release_branches(@branch_prefix)
204
+ rel = rel_branches.shift if rel_branches.size == 1
205
+
206
+ r_closed = false
207
+ r_rel_branch = nil
208
+ r_rel_branches = `git branch -a`.split(/\n/).select { |a| a[/remotes\/#{remote}\/#{@branch_prefix}/] }
209
+ r_rel_branches.map! { |b| b.strip }
210
+ if r_rel_branches.size == 1
211
+ r_rel_branch = r_rel_branches.shift[/remotes\/#{remote}\/(.*)/, 1]
212
+ else
213
+ if r_rel_branches.empty?
214
+ r_closed = true
215
+ else
216
+ raise "there are a number of remote release branches"
217
+ end
218
+ end
219
+
220
+ if rel
221
+ if r_rel_branch != rel
222
+ r_closed = true
223
+ end
224
+
225
+ if r_closed
226
+ puts "release closed! so cleanup local release branch"
227
+ puts "checkout #{develop}"
228
+ `git checkout #{develop}`
229
+ r = `git daily pull`
230
+ puts r
231
+ puts "delete #{rel}"
232
+ r = `git branch -d #{rel}`
233
+ puts r
234
+ unless $? == 0
235
+ $stderr.puts "branch delete failed"
236
+ $stderr.puts " git branch delete failed, please manually"
237
+ end
238
+
239
+ if r_rel_branch != rel
240
+ $stderr.puts "Closed old relase branch"
241
+ $stderr.puts "Please retry 'release sync'"
242
+ end
243
+ puts "sync to release close"
244
+ return
245
+ end
246
+
247
+ if cur != rel
248
+ puts "checkout #{rel}"
249
+ `git checkout #{rel}`
250
+ cur = Command.current_branch
251
+ end
252
+
253
+ puts "git pull"
254
+ r = `git daily pull`
255
+ puts r
256
+ unless $? == 0
257
+ raise "abort"
258
+ end
259
+
260
+ puts "git push"
261
+ r = `git daily push`
262
+ puts r
263
+ unless $? == 0
264
+ $stderr.puts "failed to push to remote"
265
+ raise "abort"
266
+ end
267
+ else
268
+ if r_closed
269
+ puts "sync completed (nothing to do)"
270
+ return
271
+ end
272
+
273
+ puts "checkout and traking #{r_rel_branch}"
274
+ r = `git checkout #{r_rel_branch}`
275
+ puts r
276
+ unless $? == 0
277
+ $stderr.puts "failed to checkout"
278
+ raise "abort"
279
+ end
280
+ puts "start to tracking release branch"
281
+ end
282
+ end
283
+
284
+ def list
285
+ release_branch = Command.release_branches(@branch_prefix)
286
+ if release_branch.empty?
287
+ raise "#{@branch_prefix} branch not found. abort."
288
+ end
289
+
290
+ current_branch = Command.current_branch
291
+ master_branch = Command.master
292
+
293
+ puts "first, fetch remotes"
294
+ `git fetch --all`
295
+
296
+ revs = []
297
+ rev_ids = `git rev-list --no-merges #{master_branch}..#{current_branch}`.split(/\n/)
298
+ rev_ids.each do |rev_id|
299
+ rev = {}
300
+ rev[:id] = rev_id
301
+ rev[:add_files] = []
302
+ rev[:mod_files] = []
303
+
304
+ logs = `git show #{rev_id}`
305
+ file = nil
306
+ logs.each_line do |line|
307
+ case line
308
+ when /^Author: .+\<([^@]+)@([^>]+)>/
309
+ rev[:author] = $1
310
+ when /^diff --git a\/([^ ]+) /
311
+ file = $1
312
+ when /^new file mode/
313
+ rev[:add_files] << file
314
+ when /^index/
315
+ rev[:mod_files] << file
316
+ end
317
+ end
318
+
319
+ revs << rev
320
+ end
321
+
322
+ mod_files = []
323
+ add_files = []
324
+ revs.each do |rev|
325
+ mod_files += rev[:add_files]
326
+ mod_files += rev[:mod_files]
327
+ end
328
+ mod_files.sort!.uniq!
329
+ add_files.sort!.uniq!
330
+
331
+ if revs.size > 0
332
+ puts "Commit list:"
333
+ revs.each do |rev|
334
+ puts "\t#{rev[:id]} = #{rev[:author]}"
335
+ end
336
+ puts
337
+ end
338
+
339
+ if add_files.size > 0
340
+ puts "Added files:"
341
+ add_files.each do |file|
342
+ puts "\t#{file}"
343
+ end
344
+ puts
345
+ end
346
+
347
+ if mod_files.size > 0
348
+ puts "Modified files:"
349
+ mod_files.each do |file|
350
+ puts "\t#{file}"
351
+ end
352
+ puts
353
+ end
354
+
355
+ if Command.logurl and revs.size > 0
356
+ authors = {}
357
+ revs.each do |rev|
358
+ authors[rev[:author]] = [] unless authors[rev[:author]]
359
+ authors[rev[:author]] << rev[:id]
360
+ end
361
+
362
+ logurl = Command.logurl
363
+ puts "Author list:"
364
+ authors.keys.sort.each do |key|
365
+ puts "\t#{key}:"
366
+ authors[key].each do |id|
367
+ puts sprintf("\t#{logurl}", id)
368
+ end
369
+ puts
370
+ end
371
+ end
372
+ end
373
+
374
+ def usage
375
+ <<-EOS
376
+ Usage: git daily release open\t: Open daily-release process
377
+ git daily release list\t: Show release list
378
+ git daily release sync\t: Sync current opened release process
379
+ git daily release close\t: Close to daily-release process
380
+ EOS
381
+ end
382
+ end
383
+ end
384
+ end
@@ -0,0 +1,15 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Git
4
+ module Daily
5
+ class Version < Command
6
+ def help
7
+ "version\tShow version"
8
+ end
9
+
10
+ def run
11
+ puts "git-daily : version #{Git::Daily::VERSION}"
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,96 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Git
4
+ module Daily
5
+ class Command
6
+ def initialize
7
+ end
8
+
9
+ def run
10
+ raise NotImplementedError.new("You most implement run.")
11
+ end
12
+
13
+ def help
14
+ raise NotImplementedError.new("You most implement help.")
15
+ end
16
+
17
+ def help
18
+ raise NotImplementedError.new("You most implement usage.")
19
+ end
20
+
21
+ def self.remotes
22
+ `git config --list --no-color`.split(/\n/).select {|a| a[/^remote\.([^\.]+)\.url/] }
23
+ end
24
+
25
+ def self.branches
26
+ r = `git branch --no-color`.split(/\n/)
27
+ r.map! { |b| b[/^\*/] ? b[2 .. -1] : b.strip }
28
+ end
29
+
30
+ def self.has_branch?(branch)
31
+ r = branches
32
+ r.find {|i| i == branch } ? true : false
33
+ end
34
+
35
+ def self.remote
36
+ r = `git config gitdaily.remote`
37
+ r.chomp!
38
+ r.empty? ? nil : r
39
+ end
40
+
41
+ def self.master
42
+ r = `git config gitdaily.master`
43
+ r.chomp!
44
+ r.empty? ? nil : r
45
+ end
46
+
47
+ def self.develop
48
+ r = `git config gitdaily.develop`
49
+ r.chomp!
50
+ r.empty? ? nil : r
51
+ end
52
+
53
+ def self.logurl
54
+ r = `git config gitdaily.logurl`
55
+ r.chomp!
56
+ r.empty? ? nil : r
57
+ end
58
+
59
+ def self.current_branch
60
+ r = `git branch --no-color`.split(/\n/)
61
+ master = r.select { |v| v[/^\*/] }
62
+ return nil if master.empty?
63
+ master[0][/^\* (.*)/, 1]
64
+ end
65
+
66
+ def self.remote_branch(remote, current_branch)
67
+ r = `git branch --no-color -a`.split(/\n/).select { |a| a[/remotes\/#{remote}\/#{current_branch}/] }
68
+ return nil if r.empty?
69
+ r[0].strip
70
+ end
71
+
72
+ def self.has_remote_branch?(remote, branch)
73
+ if remote_branch(remote, branch)
74
+ true
75
+ else
76
+ false
77
+ end
78
+ end
79
+
80
+ def self.clean?
81
+ r = `git status -uno -s`.split(/\n/)
82
+ r.empty? ? true : false
83
+ end
84
+
85
+ def self.release_branches(branch)
86
+ r = `git branch --no-color`.split(/\n/).select { |a| a[/#{branch}/] }
87
+ r.map! { |b| b[/^\*/] ? b[2 .. -1] : b.strip }
88
+ end
89
+
90
+ def self.merged_branches
91
+ r = `git branch --no-color --merged`.split(/\n/)
92
+ r.map! { |b| b[/^\*/] ? b[2 .. -1] : b.strip }
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,19 @@
1
+ require "git-daily/application"
2
+
3
+ module Git
4
+ module Daily
5
+ class << self
6
+ def application
7
+ @application ||= Git::Daily::Application.new
8
+ end
9
+
10
+ def application=(app)
11
+ @application = app
12
+ end
13
+
14
+ def original_dir
15
+ application.original_dir
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ module Git
2
+ module Daily
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
data/lib/git-daily.rb ADDED
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require "optparse"
4
+ require "ostruct"
5
+ require "shellwords"
6
+
7
+ require "git-daily/version"
8
+ require "git-daily/command"
9
+ require "git-daily/application"
10
+ require "git-daily/git-daily-module"
11
+
@@ -0,0 +1,10 @@
1
+ require 'test/unit'
2
+ require 'git-daily'
3
+
4
+ class TestApplication < Test::Unit::TestCase
5
+ def test_load_commands
6
+ r = Git::Daily.application.load_commands
7
+ assert(r.detect {|v| v[/config/]})
8
+ assert(r.detect {|v| v[/init/]})
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'test/unit'
4
+ require 'git-daily'
5
+ require 'git-daily/command/init'
6
+
7
+ class TestCommandInit < Test::Unit::TestCase
8
+ def test_init
9
+ command = Git::Daily::Init.new
10
+
11
+ $stdin = File.new(File.join(File.dirname(__FILE__), 'test_init_input.txt'))
12
+ assert_nil command.run
13
+ end
14
+
15
+ def teardown
16
+ $stdin.close
17
+ $stdout = STDIN
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'test/unit'
4
+ require 'git-daily'
5
+ require 'git-daily/command/init'
6
+
7
+ class TestCommandRelease < Test::Unit::TestCase
8
+ def setup
9
+ @command = Git::Daily::Release.new
10
+ end
11
+
12
+ def test_relase_open
13
+ @command.open
14
+ end
15
+
16
+ def test_release_list
17
+ @command.list
18
+ end
19
+
20
+ def teardown
21
+ $stdin = STDIN
22
+ end
23
+ end
@@ -0,0 +1 @@
1
+
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: git-daily
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Koichiro Ohba
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-27 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: ! 'git-daily on Ruby is a tool which helps you to do daily workflow easier
15
+ on Git. This is the Ruby version. The original PHP version is here: https://github.com/sotarok/git-daily'
16
+ email:
17
+ - koichiro@meadowy.org
18
+ executables:
19
+ - git-daily
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - .gitignore
24
+ - Gemfile
25
+ - LICENSE
26
+ - README.rst
27
+ - Rakefile
28
+ - bin/git-daily
29
+ - git-daily.gemspec
30
+ - lib/git-daily.rb
31
+ - lib/git-daily/application.rb
32
+ - lib/git-daily/command.rb
33
+ - lib/git-daily/command/config.rb
34
+ - lib/git-daily/command/help.rb
35
+ - lib/git-daily/command/hotfix.rb
36
+ - lib/git-daily/command/init.rb
37
+ - lib/git-daily/command/pull.rb
38
+ - lib/git-daily/command/push.rb
39
+ - lib/git-daily/command/release.rb
40
+ - lib/git-daily/command/version.rb
41
+ - lib/git-daily/git-daily-module.rb
42
+ - lib/git-daily/version.rb
43
+ - test/test_application.rb
44
+ - test/test_command_init.rb
45
+ - test/test_command_release.rb
46
+ - test/test_init_input.txt
47
+ homepage: https://github.com/koichiro/git-daily
48
+ licenses: []
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project: git-daily
67
+ rubygems_version: 1.8.11
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: git-daily on ruby is a tool which helps you to do daily workflow easier on
71
+ Git.
72
+ test_files:
73
+ - test/test_application.rb
74
+ - test/test_command_init.rb
75
+ - test/test_command_release.rb
76
+ - test/test_init_input.txt
77
+ has_rdoc: