falkorlib 0.1.0 → 0.2.8
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +56 -4
- data/README.md +147 -34
- data/Rakefile +42 -23
- data/falkorlib.gemspec +11 -7
- data/lib/falkorlib.rb +31 -2
- data/lib/falkorlib/common.rb +93 -41
- data/lib/falkorlib/config.rb +91 -0
- data/lib/falkorlib/git.rb +15 -0
- data/lib/falkorlib/git/base.rb +405 -0
- data/lib/falkorlib/git/flow.rb +120 -0
- data/lib/falkorlib/git_tasks.rb +56 -0
- data/lib/falkorlib/loader.rb +9 -1
- data/lib/falkorlib/tasks.rb +30 -0
- data/lib/falkorlib/tasks/git.rake +121 -0
- data/lib/falkorlib/tasks/git.rb +56 -0
- data/lib/falkorlib/tasks/gitflow.rake +139 -0
- data/{tasks/spec_test.rake → lib/falkorlib/tasks/rspec.rake} +4 -3
- data/lib/falkorlib/tasks/yard.rake +78 -0
- data/lib/falkorlib/version.rb +62 -54
- data/lib/falkorlib/versioning.rb +162 -0
- data/spec/falkorlib/common_spec.rb +12 -12
- data/spec/falkorlib/git_spec.rb +191 -0
- data/spec/falkorlib/gitflow_spec.rb +47 -45
- data/spec/falkorlib/versioning_spec.rb +108 -0
- data/spec/spec_helper.rb +58 -9
- metadata +80 -24
- data/lib/falkorlib/gitflow.rb +0 -71
- data/tasks/debug_mail.rake +0 -75
- data/tasks/debug_mail.txt +0 -13
- data/tasks/gem.rake +0 -73
- data/tasks/unit_test.rake +0 -77
- data/tasks/yard.rake +0 -51
- data/test/test_gitflow.rb +0 -16
data/lib/falkorlib.rb
CHANGED
|
@@ -1,10 +1,39 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
################################################################################
|
|
3
|
+
# Time-stamp: <Ven 2014-06-06 17:06 svarrette>
|
|
4
|
+
################################################################################
|
|
5
|
+
# _____ _ _ _ _ _
|
|
6
|
+
# | ___|_ _| | | _____ _ __| | (_) |__
|
|
7
|
+
# | |_ / _` | | |/ / _ \| '__| | | | '_ \
|
|
8
|
+
# | _| (_| | | < (_) | | | |___| | |_) |
|
|
9
|
+
# |_| \__,_|_|_|\_\___/|_| |_____|_|_.__/
|
|
1
10
|
#
|
|
2
|
-
|
|
11
|
+
################################################################################
|
|
12
|
+
# @author Sebastien Varrette <Sebastien.Varrette@uni.lu>
|
|
3
13
|
#
|
|
14
|
+
# * [Source code](https://github.com/Falkor/falkorlib)
|
|
15
|
+
# * [Official Gem](https://rubygems.org/gems/falkorlib)
|
|
16
|
+
################################################################################
|
|
17
|
+
|
|
18
|
+
require "awesome_print"
|
|
19
|
+
|
|
20
|
+
begin
|
|
21
|
+
require 'term/ansicolor'
|
|
22
|
+
COLOR = true
|
|
23
|
+
rescue Exception => e
|
|
24
|
+
puts "/!\\ cannot find the 'term/ansicolor' library"
|
|
25
|
+
puts " Consider installing it by 'gem install term-ansicolor'"
|
|
26
|
+
COLOR = false
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
require 'yaml'
|
|
30
|
+
|
|
31
|
+
# Sebastien Varrette aka Falkor's Common library to share Ruby code
|
|
32
|
+
# and `{rake,cap}` tasks
|
|
4
33
|
module FalkorLib
|
|
5
34
|
|
|
6
35
|
end # module FalkorLib
|
|
7
36
|
|
|
8
37
|
require "falkorlib/version"
|
|
9
38
|
require "falkorlib/loader"
|
|
10
|
-
|
|
39
|
+
|
data/lib/falkorlib/common.rb
CHANGED
|
@@ -1,23 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
module
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
################################################################################
|
|
3
|
+
# Time-stamp: <Jeu 2014-06-19 18:10 svarrette>
|
|
4
|
+
################################################################################
|
|
5
|
+
|
|
6
|
+
require "falkorlib"
|
|
7
|
+
require 'open3'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
module FalkorLib #:nodoc:
|
|
11
|
+
|
|
12
|
+
# @abstract
|
|
13
|
+
# Recipe for all my toolbox and versatile Ruby functions I'm using
|
|
14
|
+
# everywhere.
|
|
15
|
+
# You'll typically want to include the `FalkorLib::Common` module to bring
|
|
16
|
+
# the corresponding definitions into yoru scope.
|
|
17
|
+
#
|
|
18
|
+
# @example:
|
|
19
|
+
# require 'falkorlib'
|
|
20
|
+
# include FalkorLib::Common
|
|
21
|
+
#
|
|
22
|
+
# info 'exemple of information text'
|
|
23
|
+
# really_continue?
|
|
24
|
+
# run %{ echo 'this is an executed command' }
|
|
25
|
+
#
|
|
26
|
+
# Falkor.config.debug = true
|
|
27
|
+
# run %{ echo 'this is a simulated command that *will not* be executed' }
|
|
28
|
+
# error "that's an error text, let's exit with status code 1"
|
|
29
|
+
#
|
|
16
30
|
module Common
|
|
17
|
-
|
|
31
|
+
module_function
|
|
18
32
|
##################################
|
|
19
33
|
### Default printing functions ###
|
|
20
34
|
##################################
|
|
35
|
+
# Print a text in bold
|
|
36
|
+
def bold(str)
|
|
37
|
+
COLOR == true ? Term::ANSIColor.bold(str) : str
|
|
38
|
+
end
|
|
21
39
|
|
|
22
40
|
# Print a text in green
|
|
23
41
|
def green(str)
|
|
@@ -43,15 +61,16 @@ module FalkorLib
|
|
|
43
61
|
def warning(str)
|
|
44
62
|
puts cyan("/!\\ WARNING: " + str)
|
|
45
63
|
end
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
end
|
|
64
|
+
alias :warn :warning
|
|
65
|
+
|
|
49
66
|
## Print an error message and abort
|
|
50
67
|
def error(str)
|
|
51
68
|
#abort red("*** ERROR *** " + str)
|
|
52
|
-
|
|
53
|
-
|
|
69
|
+
$stderr.puts red("*** ERROR *** " + str)
|
|
70
|
+
exit 1
|
|
54
71
|
end
|
|
72
|
+
|
|
73
|
+
## simple helper text to mention a non-implemented feature
|
|
55
74
|
def not_implemented()
|
|
56
75
|
error("NOT YET IMPLEMENTED")
|
|
57
76
|
end
|
|
@@ -83,28 +102,61 @@ module FalkorLib
|
|
|
83
102
|
|
|
84
103
|
## Check for the presence of a given command
|
|
85
104
|
def command?(name)
|
|
86
|
-
|
|
87
|
-
|
|
105
|
+
`which #{name}`
|
|
106
|
+
$?.success?
|
|
88
107
|
end
|
|
89
108
|
|
|
90
|
-
## Execute a given command
|
|
91
|
-
def
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
109
|
+
## Execute a given command, return exit code and print nicely stdout and stderr
|
|
110
|
+
def nice_execute(cmd)
|
|
111
|
+
puts bold("[Running] #{cmd.gsub(/^\s*/, ' ')}")
|
|
112
|
+
stdout, stderr, exit_status = Open3.capture3( cmd )
|
|
113
|
+
unless stdout.empty?
|
|
114
|
+
stdout.each_line do |line|
|
|
115
|
+
print "** [out] #{line}"
|
|
116
|
+
$stdout.flush
|
|
95
117
|
end
|
|
96
|
-
end
|
|
118
|
+
end
|
|
119
|
+
unless stderr.empty?
|
|
120
|
+
stderr.each_line do |line|
|
|
121
|
+
print red("** [err] #{line}")
|
|
122
|
+
$stderr.flush
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
exit_status
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Simpler version that use the system call
|
|
129
|
+
def execute(cmd)
|
|
130
|
+
puts bold("[Running] #{cmd.gsub(/^\s*/, ' ')}")
|
|
131
|
+
system(cmd)
|
|
132
|
+
$?
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
## Execute a given command - exit if status != 0
|
|
139
|
+
def exec_or_exit(cmd)
|
|
140
|
+
status = execute(cmd)
|
|
141
|
+
if (status.to_i != 0)
|
|
142
|
+
error("The command '#{cmd}' failed with exit status #{status.to_i}")
|
|
143
|
+
end
|
|
144
|
+
res
|
|
97
145
|
end
|
|
98
146
|
|
|
99
147
|
## "Nice" way to present run commands
|
|
100
148
|
## Ex: run %{ hostname -f }
|
|
101
149
|
def run(cmds)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
150
|
+
exit_status = 0
|
|
151
|
+
puts bold("[Running]\n#{cmds.gsub(/^\s*/, ' ')}")
|
|
152
|
+
$stdout.flush
|
|
153
|
+
#puts cmds.split(/\n */).inspect
|
|
154
|
+
cmds.split(/\n */).each do |cmd|
|
|
155
|
+
next if cmd.empty?
|
|
156
|
+
system("#{cmd}") unless FalkorLib.config.debug
|
|
157
|
+
exit_status = $?
|
|
158
|
+
end
|
|
159
|
+
exit_status
|
|
108
160
|
end
|
|
109
161
|
|
|
110
162
|
###############################
|
|
@@ -113,16 +165,16 @@ module FalkorLib
|
|
|
113
165
|
|
|
114
166
|
# Return the yaml content as a Hash object
|
|
115
167
|
def load_config(filepath)
|
|
116
|
-
|
|
168
|
+
YAML::load_file(filepath)
|
|
117
169
|
end
|
|
118
170
|
|
|
119
171
|
# Store the Hash object as a Yaml file
|
|
120
172
|
def store_config(filepath, hash)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
173
|
+
File.open( filepath, 'w') do |f|
|
|
174
|
+
f.print "# ", File.basename(filepath), "\n"
|
|
175
|
+
f.puts "# /!\\ DO NOT EDIT THIS FILE: it has been automatically generated"
|
|
176
|
+
f.puts hash.to_yaml
|
|
177
|
+
end
|
|
126
178
|
end
|
|
127
179
|
|
|
128
180
|
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
################################################################################
|
|
3
|
+
# Time-stamp: <Mer 2014-06-18 17:17 svarrette>
|
|
4
|
+
################################################################################
|
|
5
|
+
# FalkorLib Configuration
|
|
6
|
+
#
|
|
7
|
+
# Resources:
|
|
8
|
+
# * https://github.com/markbates/cover_me/blob/master/lib/cover_me/config.rb
|
|
9
|
+
################################################################################
|
|
10
|
+
require "falkorlib"
|
|
11
|
+
|
|
12
|
+
require "configatron"
|
|
13
|
+
require "configatron/store"
|
|
14
|
+
|
|
15
|
+
module FalkorLib #:nodoc:
|
|
16
|
+
|
|
17
|
+
class << self
|
|
18
|
+
# Yields up a configuration object when given a block.
|
|
19
|
+
# Without a block it just returns the configuration object.
|
|
20
|
+
# Uses Configatron under the covers.
|
|
21
|
+
#
|
|
22
|
+
# Example:
|
|
23
|
+
# FalkorLib.config do |c|
|
|
24
|
+
# c.foo = :bar
|
|
25
|
+
# end
|
|
26
|
+
#
|
|
27
|
+
# FalkorLib.config.foo # => :bar
|
|
28
|
+
def config(&block)
|
|
29
|
+
yield configuration if block_given?
|
|
30
|
+
configuration
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
## initiate the configuration (with default value) if needed
|
|
34
|
+
def configuration
|
|
35
|
+
@config ||= Configatron::Store.new(options = FalkorLib::Config.default)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
module Config
|
|
41
|
+
# Defaults global settings
|
|
42
|
+
DEFAULTS = {
|
|
43
|
+
:debug => false,
|
|
44
|
+
:root => Dir.pwd
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module_function
|
|
48
|
+
|
|
49
|
+
## Build the default configuration hash, to be used to initiate the default.
|
|
50
|
+
# The hash is built depending on the loaded files.
|
|
51
|
+
def default
|
|
52
|
+
res = FalkorLib::Config::DEFAULTS
|
|
53
|
+
$LOADED_FEATURES.each do |path|
|
|
54
|
+
res[:git] = FalkorLib::Config::Git::DEFAULTS if path.include?('lib/falkorlib/git.rb')
|
|
55
|
+
res[:gitflow] = FalkorLib::Config::GitFlow::DEFAULTS if path.include?('lib/falkorlib/git.rb')
|
|
56
|
+
res[:versioning] = FalkorLib::Config::Versioning::DEFAULTS if path.include?('lib/falkorlib/versioning.rb')
|
|
57
|
+
end
|
|
58
|
+
res
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# config = Thread.current[:config] ||= Configatron::Store.new
|
|
64
|
+
|
|
65
|
+
# # Singleton configuration class
|
|
66
|
+
# class Config
|
|
67
|
+
# include Singleton
|
|
68
|
+
|
|
69
|
+
# # Give memoized defaults for locked configuration options found in /config/falkorlib.yml file
|
|
70
|
+
# #
|
|
71
|
+
# # @example Usage
|
|
72
|
+
# # conf = Configuration.instance.defaults
|
|
73
|
+
# # conf.base_url #=> "http://ambito.com/economia/mercados/monedas/dolar/"
|
|
74
|
+
# # conf.blue.buy.xpath #=> "//*[@id=\"contenido\"]/div[1]/div[2]/div/div/div[2]/big"
|
|
75
|
+
# #
|
|
76
|
+
# # @return [Configatron::Store] the magic configuration instance with hash and dot '.' indifferent access
|
|
77
|
+
# def defaults
|
|
78
|
+
# return @config if @config
|
|
79
|
+
|
|
80
|
+
# @config = Configatron::Store.new
|
|
81
|
+
# file_path = File.expand_path('../../../config/falkorlib.yml', __FILE__)
|
|
82
|
+
# hash_config = YAML::load_file(file_path)
|
|
83
|
+
|
|
84
|
+
# @config.configure_from_hash(hash_config)
|
|
85
|
+
# @config.lock!
|
|
86
|
+
# @config
|
|
87
|
+
# end
|
|
88
|
+
# end
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
end # module FalkorLib
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
################################################################################
|
|
3
|
+
# Time-stamp: <Ven 2014-06-06 13:12 svarrette>
|
|
4
|
+
################################################################################
|
|
5
|
+
# Management of Git [flow] operations
|
|
6
|
+
|
|
7
|
+
require "falkorlib"
|
|
8
|
+
|
|
9
|
+
module FalkorLib #:nodoc:
|
|
10
|
+
|
|
11
|
+
end # module FalkorLib
|
|
12
|
+
|
|
13
|
+
require "falkorlib/git/base"
|
|
14
|
+
require "falkorlib/git/flow"
|
|
15
|
+
|
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
################################################################################
|
|
3
|
+
# Time-stamp: <Mer 2014-06-18 21:59 svarrette>
|
|
4
|
+
################################################################################
|
|
5
|
+
# Interface for the main Git operations
|
|
6
|
+
#
|
|
7
|
+
# On purpose, I try to avoid using the Git library to avoid instanciate the Git
|
|
8
|
+
# class and thus managing the working directory
|
|
9
|
+
|
|
10
|
+
require "falkorlib"
|
|
11
|
+
require "falkorlib/common"
|
|
12
|
+
|
|
13
|
+
require "minigit"
|
|
14
|
+
require "pathname"
|
|
15
|
+
|
|
16
|
+
include FalkorLib::Common
|
|
17
|
+
|
|
18
|
+
module FalkorLib #:nodoc:
|
|
19
|
+
module Config
|
|
20
|
+
|
|
21
|
+
# Default configuration for Git
|
|
22
|
+
module Git
|
|
23
|
+
# Git defaults for FalkorLib
|
|
24
|
+
DEFAULTS = {
|
|
25
|
+
:submodulesdir => '.submodules',
|
|
26
|
+
:submodules => {},
|
|
27
|
+
:subtrees => {}
|
|
28
|
+
}
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Management of Git operations
|
|
33
|
+
module Git
|
|
34
|
+
module_function
|
|
35
|
+
|
|
36
|
+
## Check if a git directory has been initialized
|
|
37
|
+
def init?(path = Dir.pwd)
|
|
38
|
+
begin
|
|
39
|
+
g = MiniGit.new(path)
|
|
40
|
+
rescue Exception
|
|
41
|
+
return false
|
|
42
|
+
end
|
|
43
|
+
return true
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
## Check if the repositories already holds some commits
|
|
47
|
+
def has_commits?(path)
|
|
48
|
+
res = false
|
|
49
|
+
Dir.chdir(path) do
|
|
50
|
+
stdout, stderr, exit_status = Open3.capture3( "git rev-parse HEAD" )
|
|
51
|
+
res = (exit_status == 0)
|
|
52
|
+
end
|
|
53
|
+
res
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
## Check the availability of a given git command
|
|
57
|
+
def command?(cmd, path = Dir.pwd)
|
|
58
|
+
cg = MiniGit::Capturing.new(path)
|
|
59
|
+
cmd_list = cg.help :a => true
|
|
60
|
+
# typical run:
|
|
61
|
+
# usage: git [--version] [--help] [-C <path>] [-c name=value]
|
|
62
|
+
# [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
|
|
63
|
+
# [-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
|
|
64
|
+
# [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
|
|
65
|
+
# <command> [<args>]
|
|
66
|
+
#
|
|
67
|
+
# available git commands in '/usr/local/Cellar/git/1.8.5.2/libexec/git-core'
|
|
68
|
+
#
|
|
69
|
+
# add [...] \
|
|
70
|
+
# [...] | The part we are interested in, delimited by '\n\n' sequence
|
|
71
|
+
# [...] /
|
|
72
|
+
#
|
|
73
|
+
# 'git help -a' and 'git help -g' lists available subcommands and some
|
|
74
|
+
# concept guides. See 'git help <command>' or 'git help <concept>'
|
|
75
|
+
# to read about a specific subcommand or concept
|
|
76
|
+
l = cmd_list.split("\n\n")
|
|
77
|
+
l.shift # useless first part
|
|
78
|
+
#ap l
|
|
79
|
+
subl = l.each_index.select{|i| l[i] =~ /^\s\s+/ } # find sublines that starts with at least two whitespaces
|
|
80
|
+
#ap subl
|
|
81
|
+
return false if subl.empty?
|
|
82
|
+
subl.any? { |i| l[i].split.include?(cmd) }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
## Initialize a git repository
|
|
86
|
+
def init(path = Dir.pwd)
|
|
87
|
+
# FIXME for travis test: ensure the global git configurations
|
|
88
|
+
# 'user.email' and 'user.name' are set
|
|
89
|
+
[ 'user.name', 'user.email' ].each do |userconf|
|
|
90
|
+
if MiniGit[userconf].nil?
|
|
91
|
+
warn "The Git global configuration '#{userconf}' is not set so"
|
|
92
|
+
warn "you should *seriously* consider setting them by running\n\t git config --global #{userconf} 'your_#{userconf.sub(/\./, '_')}'"
|
|
93
|
+
default_val = ENV['USER']
|
|
94
|
+
default_val += '@domain.org' if userconf =~ /email/
|
|
95
|
+
warn "Now putting a default value '#{default_val}' you could change later on"
|
|
96
|
+
run %{
|
|
97
|
+
git config --global #{userconf} "#{default_val}"
|
|
98
|
+
}
|
|
99
|
+
#MiniGit[userconf] = default_val
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
#puts "#init #{path}"
|
|
103
|
+
Dir.chdir( "#{path}" ) do
|
|
104
|
+
%x[ pwd && git init ] unless FalkorLib.config.debug
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Return the Git working tree from the proposed path (current directory by default)
|
|
109
|
+
def rootdir(path = Dir.pwd)
|
|
110
|
+
g = MiniGit.new
|
|
111
|
+
g.find_git_dir(path)[1]
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Return the git root directory for the path (current directory by default)
|
|
115
|
+
def gitdir(path = Dir.pwd)
|
|
116
|
+
g = MiniGit.new
|
|
117
|
+
g.find_git_dir(path)[0]
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Create a new branch
|
|
121
|
+
def create_branch(branch, path = Dir.pwd)
|
|
122
|
+
#ap method(__method__).parameters.map { |arg| arg[1] }
|
|
123
|
+
g = MiniGit.new(path)
|
|
124
|
+
error "not yet any commit performed -- You shall do one" unless has_commits?(path)
|
|
125
|
+
g.branch "#{branch}"
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Delete a branch.
|
|
129
|
+
def delete_branch(branch, path = Dir.pwd, opts = { :force => false })
|
|
130
|
+
g = MiniGit.new(path)
|
|
131
|
+
error "'#{branch}' is not a valid existing branch" unless list_branch(path).include?( branch )
|
|
132
|
+
g.branch (opts[:force] ? :D : :d) => "#{branch}"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
## Fetch the latest changes
|
|
136
|
+
def fetch(path = Dir.pwd)
|
|
137
|
+
Dir.chdir( path ) do
|
|
138
|
+
execute "git fetch --all -v"
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
## Get an array of the local branches present (first element is always the
|
|
143
|
+
## current branch)
|
|
144
|
+
def list_branch(path = Dir.pwd)
|
|
145
|
+
cg = MiniGit::Capturing.new(path)
|
|
146
|
+
res = cg.branch :a => true
|
|
147
|
+
res = res.split("\n")
|
|
148
|
+
# Eventually reorder to make the first element of the array the current branch
|
|
149
|
+
i = res.find_index { |e| e =~ /^\*\s/ }
|
|
150
|
+
unless (i.nil? || i == 0)
|
|
151
|
+
res[0], res[i] = res[i], res[0]
|
|
152
|
+
end
|
|
153
|
+
res.each { |e| e.sub!(/^\*?\s+/, '') }
|
|
154
|
+
res
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
## Get the current git branch
|
|
158
|
+
def branch?(path = Dir.pwd)
|
|
159
|
+
list_branch(path)[0]
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
## Grab a remote branch
|
|
163
|
+
def grab(branch, path = Dir.pwd, remote = 'origin')
|
|
164
|
+
exit_status = 1
|
|
165
|
+
error "no branch provided" if branch.nil?
|
|
166
|
+
remotes = FalkorLib::Git.remotes(path)
|
|
167
|
+
branches = FalkorLib::Git.list_branch(path)
|
|
168
|
+
Dir.chdir(FalkorLib::Git.rootdir( path ) ) do
|
|
169
|
+
if branches.include? "remotes/#{remote}/#{branch}"
|
|
170
|
+
info "Grab the branch '#{remote}/#{branch}'"
|
|
171
|
+
exit_status = execute "git branch --set-upstream #{branch} #{remote}/#{branch}"
|
|
172
|
+
else
|
|
173
|
+
warning "the remote branch '#{remote}/#{branch}' cannot be found"
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
exit_status
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
## Publish a branch on the remote
|
|
180
|
+
def publish(branch, path = Dir.pwd, remote = 'origin')
|
|
181
|
+
exit_status = 1
|
|
182
|
+
error "no branch provided" if branch.nil?
|
|
183
|
+
remotes = FalkorLib::Git.remotes(path)
|
|
184
|
+
branches = FalkorLib::Git.list_branch(path)
|
|
185
|
+
Dir.chdir(FalkorLib::Git.rootdir( path ) ) do
|
|
186
|
+
if branches.include? "remotes/#{remote}/#{branch}"
|
|
187
|
+
warning "the remote branch '#{remote}/#{branch}' already exists"
|
|
188
|
+
else
|
|
189
|
+
info "Publish the branch '#{branch}' on the remote '#{remote}'"
|
|
190
|
+
exit_status = run %{
|
|
191
|
+
git push #{remote} #{branch}:refs/heads/#{branch}
|
|
192
|
+
git fetch #{remote}
|
|
193
|
+
git branch --set-upstream-to #{remote}/#{branch} #{branch}
|
|
194
|
+
}
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
exit_status
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
## List the files currently version
|
|
201
|
+
def list_files(path = Dir.pwd)
|
|
202
|
+
g = MiniGit.new(path)
|
|
203
|
+
g.capturing.ls_files.split
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
## Add a file/whatever to Git and commit it
|
|
209
|
+
def add(path, msg = "")
|
|
210
|
+
exit_status = 0
|
|
211
|
+
dir = File.realpath File.dirname(path)
|
|
212
|
+
root = rootdir(path)
|
|
213
|
+
relative_path_to_root = Pathname.new( File.realpath(path) ).relative_path_from Pathname.new(root)
|
|
214
|
+
real_msg = (msg.empty? ? "add '#{relative_path_to_root}'" : msg)
|
|
215
|
+
Dir.chdir( dir ) do
|
|
216
|
+
exit_status = run %{
|
|
217
|
+
git add #{path}
|
|
218
|
+
git commit -s -m "#{real_msg}" #{path}
|
|
219
|
+
}
|
|
220
|
+
end
|
|
221
|
+
exit_status.to_i
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
## Check if a git directory is in dirty mode
|
|
225
|
+
# git diff --shortstat 2> /dev/null | tail -n1
|
|
226
|
+
def dirty?(path = Dir.pwd)
|
|
227
|
+
g = MiniGit.new(path)
|
|
228
|
+
a = g.capturing.diff :shortstat => true
|
|
229
|
+
#ap a
|
|
230
|
+
! a.empty?
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
## Get the last tag commit, or nil if no tag can be found
|
|
234
|
+
def last_tag_commit(path = Dir.pwd)
|
|
235
|
+
res = nil
|
|
236
|
+
g = MiniGit.new(path)
|
|
237
|
+
# git rev-list --tags --max-count=1)
|
|
238
|
+
a = g.capturing.rev_list :tags => true, :max_count => 1
|
|
239
|
+
a
|
|
240
|
+
end # last_tag_commit
|
|
241
|
+
|
|
242
|
+
## List of Git remotes
|
|
243
|
+
def remotes(path = Dir.pwd)
|
|
244
|
+
g = MiniGit.new(path)
|
|
245
|
+
g.capturing.remote.split()
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
## Initialize git subtrees from the configuration
|
|
249
|
+
def submodule_init(path = Dir.pwd)
|
|
250
|
+
exit_status = 1
|
|
251
|
+
git_root_dir = rootdir(path)
|
|
252
|
+
if File.exists?("#{git_root_dir}/.gitmodules")
|
|
253
|
+
unless FalkorLib.config.git[:submodules].empty?
|
|
254
|
+
# TODO: Check if it contains all submodules of the configuration
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
#ap FalkorLib.config.git
|
|
258
|
+
Dir.chdir(git_root_dir) do
|
|
259
|
+
exit_status = FalkorLib::Git.submodule_update( git_root_dir )
|
|
260
|
+
FalkorLib.config.git[:submodules].each do |subdir,conf|
|
|
261
|
+
next if conf[:url].nil?
|
|
262
|
+
url = conf[:url]
|
|
263
|
+
dir = "#{FalkorLib.config.git[:submodulesdir]}/#{subdir}"
|
|
264
|
+
branch = conf[:branch].nil? ? 'master' : conf[:branch]
|
|
265
|
+
unless File.directory?( dir )
|
|
266
|
+
info "Adding Git submodule '#{dir}' from '#{url}'"
|
|
267
|
+
exit_status = run %{
|
|
268
|
+
git submodule add -b #{branch} #{url} #{dir}
|
|
269
|
+
git commit -s -m "Add Git submodule '#{dir}' from '#{url}'" .gitmodules #{dir}
|
|
270
|
+
}
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
exit_status
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
## Update the Git submodules to the **local** registered version
|
|
278
|
+
def submodule_update(path = Dir.pwd)
|
|
279
|
+
exit_status = 1
|
|
280
|
+
git_root_dir = rootdir(path)
|
|
281
|
+
Dir.chdir(git_root_dir) do
|
|
282
|
+
exit_status = run %{
|
|
283
|
+
git submodule init
|
|
284
|
+
git submodule update
|
|
285
|
+
}
|
|
286
|
+
end
|
|
287
|
+
exit_status
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
## Upgrade the Git submodules to the latest HEAD version from the remote
|
|
291
|
+
def submodule_upgrade(path = Dir.pwd)
|
|
292
|
+
exit_status = 1
|
|
293
|
+
git_root_dir = rootdir(path)
|
|
294
|
+
Dir.chdir(git_root_dir) do
|
|
295
|
+
exit_status = run %{
|
|
296
|
+
git submodule foreach 'git fetch origin; git checkout $(git rev-parse --abbrev-ref HEAD); git reset --hard origin/$(git rev-parse --abbrev-ref HEAD); git submodule update --recursive; git clean -dfx'
|
|
297
|
+
}
|
|
298
|
+
end
|
|
299
|
+
exit_status
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
## Initialize git subtrees from the configuration
|
|
304
|
+
def subtree_init(path = Dir.pwd)
|
|
305
|
+
raise ArgumentError, "Git 'subtree' command is not available" unless FalkorLib::Git.command? "subtree"
|
|
306
|
+
if FalkorLib.config.git[:subtrees].empty?
|
|
307
|
+
FalkorLib::Git.config_warn(:subtrees)
|
|
308
|
+
return 1
|
|
309
|
+
end
|
|
310
|
+
exit_status = 0
|
|
311
|
+
git_root_dir = rootdir(path)
|
|
312
|
+
Dir.chdir(git_root_dir) do
|
|
313
|
+
FalkorLib.config.git[:subtrees].each do |dir,conf|
|
|
314
|
+
next if conf[:url].nil?
|
|
315
|
+
url = conf[:url]
|
|
316
|
+
remote = dir
|
|
317
|
+
branch = conf[:branch].nil? ? 'master' : conf[:branch]
|
|
318
|
+
remotes = FalkorLib::Git.remotes
|
|
319
|
+
unless remotes.include?( remote )
|
|
320
|
+
info "Initialize Git remote '#{remote}' from URL '#{url}'"
|
|
321
|
+
exit_status = execute "git remote add -f #{dir} #{url}"
|
|
322
|
+
end
|
|
323
|
+
unless File.directory?( File.join(git_root_dir, dir) )
|
|
324
|
+
info "initialize Git subtree '#{dir}'"
|
|
325
|
+
exit_status = execute "git subtree add --prefix #{dir} --squash #{remote}/#{branch}"
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
end
|
|
330
|
+
exit_status
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
## Show difference between local subtree(s) and their remotes"
|
|
334
|
+
def subtree_diff(path = Dir.pwd)
|
|
335
|
+
raise ArgumentError, "Git 'subtree' command is not available" unless FalkorLib::Git.command? "subtree"
|
|
336
|
+
if FalkorLib.config.git[:subtrees].empty?
|
|
337
|
+
FalkorLib::Git.config_warn(:subtrees)
|
|
338
|
+
return 1
|
|
339
|
+
end
|
|
340
|
+
exit_status = 0
|
|
341
|
+
git_root_dir = rootdir(path)
|
|
342
|
+
Dir.chdir(git_root_dir) do
|
|
343
|
+
FalkorLib.config.git[:subtrees].each do |dir,conf|
|
|
344
|
+
next if conf[:url].nil?
|
|
345
|
+
url = conf[:url]
|
|
346
|
+
remote = dir
|
|
347
|
+
branch = conf[:branch].nil? ? 'master' : conf[:branch]
|
|
348
|
+
remotes = FalkorLib::Git.remotes
|
|
349
|
+
raise IOError, "The git remote '#{remote}' is not configured" unless remotes.include?( remote )
|
|
350
|
+
raise IOError, "The git subtree directory '#{dir}' does not exists" unless File.directory? ( File.join(git_root_dir, dir) )
|
|
351
|
+
info "Git diff on subtree '#{dir}' with remote '#{remote}/#{branch}'"
|
|
352
|
+
exit_status = execute "git diff #{remote}/#{branch} #{FalkorLib::Git.branch?( git_root_dir )}:#{dir}"
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
exit_status
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
# Pull the latest changes, assuming the git repository is not dirty
|
|
359
|
+
def subtree_up(path = Dir.pwd)
|
|
360
|
+
error "Unable to pull subtree(s): Dirty Git repository" if FalkorLib::Git.dirty?( path )
|
|
361
|
+
exit_status = 0
|
|
362
|
+
git_root_dir = rootdir(path)
|
|
363
|
+
Dir.chdir(git_root_dir) do
|
|
364
|
+
FalkorLib.config.git[:subtrees].each do |dir,conf|
|
|
365
|
+
next if conf[:url].nil?
|
|
366
|
+
url = conf[:url]
|
|
367
|
+
remote = dir
|
|
368
|
+
branch = conf[:branch].nil? ? 'master' : conf[:branch]
|
|
369
|
+
remotes = FalkorLib::Git.remotes
|
|
370
|
+
info "Pulling changes into subtree '#{dir}' using remote '#{remote}/#{branch}'"
|
|
371
|
+
raise IOError, "The git remote '#{remote}' is not configured" unless remotes.include?( remote )
|
|
372
|
+
info "\t\\__ fetching remote '#{remotes.join(',')}'"
|
|
373
|
+
FalkorLib::Git.fetch( git_root_dir )
|
|
374
|
+
raise IOError, "The git subtree directory '#{dir}' does not exists" unless File.directory? ( File.join(git_root_dir, dir) )
|
|
375
|
+
info "\t\\__ pulling changes"
|
|
376
|
+
exit_status = execute "git subtree pull --prefix #{dir} --squash #{remote} #{branch}"
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
exit_status
|
|
380
|
+
end
|
|
381
|
+
alias :subtree_pull :subtree_up
|
|
382
|
+
|
|
383
|
+
# Raise a warning message if subtree/submodule section is not present
|
|
384
|
+
def config_warn(type = :subtrees)
|
|
385
|
+
warn "You shall setup 'FalkorLib.config.git[#{type.to_sym}]' to configure #{type} as follows:"
|
|
386
|
+
warn " FalkorLib.config.git do |c|"
|
|
387
|
+
warn " c[#{type.to_sym}] = {"
|
|
388
|
+
warn " '<subdir>' => {"
|
|
389
|
+
warn " :url => '<giturl>',"
|
|
390
|
+
warn " :branch => 'develop' # if different from master"
|
|
391
|
+
warn " },"
|
|
392
|
+
warn " }"
|
|
393
|
+
warn " end"
|
|
394
|
+
if type == :submodules
|
|
395
|
+
warn "This will configure the Git submodule into FalkorLib.config.git.submodulesdir i.e. '#{ FalkorLib.config.git.submodulesdir}'"
|
|
396
|
+
end
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
end # module FalkorLib::Git
|
|
405
|
+
end # module FalkorLib
|