rubycut-babushka 0.10.8 → 0.15.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/Gemfile.lock +17 -15
- data/README.markdown +163 -41
- data/Rakefile +1 -1
- data/bin/babushka +1 -1
- data/deps/apt.rb +44 -0
- data/deps/babushka.rb +54 -42
- data/deps/deprecated.rb +16 -0
- data/deps/dev.rb +28 -3
- data/deps/git.rb +27 -12
- data/deps/homebrew.rb +2 -2
- data/deps/packages.rb +14 -15
- data/deps/pkg_managers.rb +21 -75
- data/deps/ruby.rb +5 -19
- data/deps/rubygems.rb +3 -3
- data/deps/system.rb +2 -2
- data/deps/templates/app.rb +60 -41
- data/deps/templates/bin.rb +16 -0
- data/deps/templates/installer.rb +9 -9
- data/deps/templates/lib.rb +17 -0
- data/deps/templates/managed.rb +1 -38
- data/deps/templates/src.rb +16 -8
- data/deps/templates/task.rb +11 -0
- data/deps/templates/tmbundle.rb +16 -2
- data/lib/babushka.rb +2 -3
- data/lib/babushka/accepts_block_for.rb +5 -3
- data/lib/babushka/asset.rb +172 -0
- data/lib/babushka/base.rb +37 -8
- data/lib/babushka/bug_reporter.rb +6 -6
- data/lib/babushka/cmdline.rb +11 -10
- data/lib/babushka/cmdline/handler.rb +7 -3
- data/lib/babushka/cmdline/helpers.rb +15 -23
- data/lib/babushka/cmdline/parser.rb +1 -1
- data/lib/babushka/core_patches/object.rb +1 -1
- data/lib/babushka/core_patches/string.rb +8 -3
- data/lib/babushka/current_ruby.rb +44 -0
- data/lib/babushka/dep.rb +111 -185
- data/lib/babushka/dep_context.rb +8 -3
- data/lib/babushka/dep_definer.rb +45 -15
- data/lib/babushka/dep_pool.rb +5 -8
- data/lib/babushka/{meta_dep.rb → dep_template.rb} +21 -2
- data/lib/babushka/dsl.rb +3 -0
- data/lib/babushka/git_repo.rb +143 -49
- data/lib/babushka/helpers/git_helpers.rb +7 -6
- data/lib/babushka/helpers/log_helpers.rb +51 -13
- data/lib/babushka/helpers/path_helpers.rb +5 -7
- data/lib/babushka/helpers/run_helpers.rb +15 -55
- data/lib/babushka/helpers/shell_helpers.rb +18 -26
- data/lib/babushka/helpers/uri_helpers.rb +9 -18
- data/lib/babushka/lambda_chooser.rb +20 -13
- data/lib/babushka/parameter.rb +20 -4
- data/lib/babushka/path_checker.rb +72 -0
- data/lib/babushka/pkg_helper.rb +38 -13
- data/lib/babushka/pkg_helpers/apt_helper.rb +15 -8
- data/lib/babushka/pkg_helpers/binpkgsrc_helper.rb +15 -14
- data/lib/babushka/pkg_helpers/binports_helper.rb +7 -7
- data/lib/babushka/pkg_helpers/brew_helper.rb +17 -25
- data/lib/babushka/pkg_helpers/gem_helper.rb +36 -27
- data/lib/babushka/pkg_helpers/npm_helper.rb +9 -9
- data/lib/babushka/pkg_helpers/pacman_helper.rb +5 -4
- data/lib/babushka/pkg_helpers/pip_helper.rb +14 -10
- data/lib/babushka/pkg_helpers/unknown_pkg_helper.rb +19 -0
- data/lib/babushka/pkg_helpers/yum_helper.rb +1 -1
- data/lib/babushka/popen.rb +13 -10
- data/lib/babushka/prompt.rb +14 -1
- data/lib/babushka/renderable.rb +11 -9
- data/lib/babushka/resource.rb +5 -166
- data/lib/babushka/run_reporter.rb +12 -3
- data/lib/babushka/shell.rb +54 -44
- data/lib/babushka/source.rb +41 -20
- data/lib/babushka/source_pool.rb +20 -13
- data/lib/babushka/system_definitions.rb +11 -3
- data/lib/babushka/system_detector.rb +31 -0
- data/lib/babushka/system_matcher.rb +53 -0
- data/lib/babushka/system_profile.rb +67 -89
- data/lib/babushka/task.rb +36 -8
- data/lib/babushka/{meta_dep_context.rb → templated_dep_context.rb} +1 -1
- data/lib/babushka/vars.rb +46 -4
- data/lib/babushka/version_of.rb +35 -17
- data/lib/babushka/version_str.rb +12 -8
- data/lib/components.rb +9 -8
- data/lib/fancypath/fancypath.rb +109 -83
- data/lib/inkan/inkan.rb +14 -14
- data/lib/{babushka → levenshtein}/levenshtein.rb +0 -0
- data/spec/acceptance/acceptance.rb +4 -4
- data/spec/acceptance_helper.rb +10 -6
- data/spec/babushka/accepts_for_spec.rb +137 -142
- data/spec/babushka/accepts_for_support.rb +13 -6
- data/spec/babushka/asset_spec.rb +165 -0
- data/spec/babushka/cmdline/help_spec.rb +11 -9
- data/spec/babushka/cmdline/meet_spec.rb +15 -0
- data/spec/babushka/cmdline/version_spec.rb +1 -1
- data/spec/babushka/core_patches_spec.rb +9 -0
- data/spec/babushka/current_ruby_spec.rb +73 -0
- data/spec/babushka/dep_context_spec.rb +27 -13
- data/spec/babushka/dep_definer_spec.rb +108 -16
- data/spec/babushka/dep_spec.rb +87 -104
- data/spec/babushka/dep_template_spec.rb +176 -0
- data/spec/babushka/deps_spec.rb +48 -19
- data/spec/babushka/gem_helper_spec.rb +46 -59
- data/spec/babushka/git_repo_spec.rb +242 -51
- data/spec/babushka/ip_spec.rb +11 -11
- data/spec/babushka/lambda_chooser_spec.rb +47 -9
- data/spec/babushka/parameter_spec.rb +21 -0
- data/spec/babushka/path_checker_spec.rb +35 -0
- data/spec/babushka/path_helpers_spec.rb +51 -50
- data/spec/babushka/prompt_spec.rb +4 -4
- data/spec/babushka/renderable_spec.rb +61 -28
- data/spec/babushka/shell_helpers_spec.rb +110 -85
- data/spec/babushka/shell_spec.rb +15 -0
- data/spec/babushka/source_pool_spec.rb +204 -210
- data/spec/babushka/source_spec.rb +125 -42
- data/spec/babushka/source_support.rb +1 -1
- data/spec/babushka/system_profile_spec.rb +86 -49
- data/spec/babushka/task_spec.rb +80 -13
- data/spec/babushka/vars_spec.rb +2 -1
- data/spec/babushka/version_of_spec.rb +29 -2
- data/spec/babushka/version_str_spec.rb +91 -65
- data/spec/babushka/xml_string_spec.rb +1 -1
- data/spec/deps/bad/broken.rb +2 -2
- data/spec/deps/bad/working.rb +0 -1
- data/spec/deps/good/{meta.rb → template.rb} +0 -0
- data/spec/deps/good/test.rb +0 -3
- data/spec/deps/outer/deps.rb +0 -2
- data/spec/fancypath/fancypath_spec.rb +30 -0
- data/spec/inkan/inkan_spec.rb +34 -32
- data/spec/spec_helper.rb +7 -50
- data/spec/system_detector_spec.rb +70 -0
- metadata +163 -177
- data/deps/os_x.rb +0 -33
- data/deps/templates/ppa.rb +0 -24
- data/lib/babushka/core_patches/io.rb +0 -8
- data/lib/babushka/dep_runner.rb +0 -85
- data/lib/babushka/helpers/suggest_helpers.rb +0 -16
- data/lib/babushka/pkg_helpers/base_helper.rb +0 -19
- data/lib/babushka/pkg_helpers/macports_helper.rb +0 -22
- data/spec/babushka/dep_definer_support.rb +0 -36
- data/spec/babushka/meta_dep_definer_spec.rb +0 -127
- data/spec/babushka/meta_dep_wrapper_spec.rb +0 -32
- data/spec/babushka/resource_spec.rb +0 -141
- data/spec/babushka/run_helpers_spec.rb +0 -26
- data/spec/babushka/source_pool_support.rb +0 -31
data/lib/babushka/dep_context.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
module Babushka
|
2
2
|
class DepContext < DepDefiner
|
3
|
-
include
|
3
|
+
include GitHelpers
|
4
|
+
include UriHelpers
|
4
5
|
|
5
|
-
accepts_list_for :desc
|
6
6
|
accepts_list_for :requires
|
7
7
|
accepts_list_for :requires_when_unmet
|
8
|
-
accepts_value_for :run_in
|
9
8
|
|
10
9
|
accepts_block_for :setup
|
11
10
|
accepts_block_for :met?
|
@@ -14,5 +13,11 @@ module Babushka
|
|
14
13
|
accepts_block_for :before
|
15
14
|
accepts_block_for :meet
|
16
15
|
accepts_block_for :after
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def in_path? provided_list
|
20
|
+
PathChecker.in_path? provided_list
|
21
|
+
end
|
17
22
|
end
|
18
23
|
end
|
data/lib/babushka/dep_definer.rb
CHANGED
@@ -31,15 +31,27 @@ module Babushka
|
|
31
31
|
@dependency = dep
|
32
32
|
@payload = {}
|
33
33
|
@block = block
|
34
|
+
@loaded, @failed = false, false
|
35
|
+
@current_platform = nil
|
34
36
|
end
|
35
37
|
|
36
|
-
def
|
37
|
-
|
38
|
+
def loaded?; @loaded end
|
39
|
+
def failed?; @failed end
|
38
40
|
|
39
|
-
|
40
|
-
|
41
|
-
|
41
|
+
def define!
|
42
|
+
unless loaded? || failed?
|
43
|
+
define_elements!
|
44
|
+
@loaded, @failed = true, false
|
42
45
|
end
|
46
|
+
self
|
47
|
+
rescue StandardError => e
|
48
|
+
@loaded, @failed = false, true
|
49
|
+
raise e
|
50
|
+
end
|
51
|
+
|
52
|
+
def invoke task_name
|
53
|
+
define! unless loaded?
|
54
|
+
instance_eval(&send(task_name)) unless failed?
|
43
55
|
end
|
44
56
|
|
45
57
|
def result message, opts = {}
|
@@ -49,31 +61,45 @@ module Babushka
|
|
49
61
|
end
|
50
62
|
|
51
63
|
def met message
|
52
|
-
|
64
|
+
removed! :instead => "a truthy return value from met?{} (maybe using #log_ok)"
|
53
65
|
end
|
54
66
|
|
55
67
|
def unmet message
|
56
|
-
|
68
|
+
removed! :instead => "a falsey return value from met?{} (maybe using #log)"
|
57
69
|
end
|
58
70
|
|
59
71
|
def unmeetable message
|
72
|
+
removed! :instead => "#unmeetable!"
|
73
|
+
end
|
74
|
+
|
75
|
+
def unmeetable! message
|
60
76
|
raise Babushka::UnmeetableDep, message
|
61
77
|
end
|
62
78
|
|
63
|
-
def
|
64
|
-
|
79
|
+
def source_location
|
80
|
+
get_source_location_for(block)
|
65
81
|
end
|
66
82
|
|
67
|
-
def
|
68
|
-
|
83
|
+
def source_location_for block_name
|
84
|
+
get_source_location_for send(block_name) if has_block? block_name
|
69
85
|
end
|
70
86
|
|
71
|
-
def
|
72
|
-
blk.
|
87
|
+
def get_source_location_for blk
|
88
|
+
if blk.respond_to?(:source_location) # Not present on cruby-1.8.
|
89
|
+
blk.source_location
|
90
|
+
else
|
91
|
+
blk.inspect.scan(/\#\<Proc\:0x[0-9a-f]+\@([^:]+):(\d+)>/).flatten
|
92
|
+
end
|
73
93
|
end
|
74
94
|
|
75
95
|
private
|
76
96
|
|
97
|
+
def define_elements!
|
98
|
+
debug "(defining #{dependency.name} against #{dependency.template.contextual_name})"
|
99
|
+
define_params!
|
100
|
+
instance_eval(&block) unless block.nil?
|
101
|
+
end
|
102
|
+
|
77
103
|
def define_params!
|
78
104
|
dependency.params.each {|param|
|
79
105
|
if respond_to?(param)
|
@@ -87,7 +113,11 @@ module Babushka
|
|
87
113
|
end
|
88
114
|
|
89
115
|
def pkg_manager
|
90
|
-
|
116
|
+
UnknownPkgHelper
|
117
|
+
end
|
118
|
+
|
119
|
+
def current_platform
|
120
|
+
@current_platform
|
91
121
|
end
|
92
122
|
|
93
123
|
def on platform, &blk
|
@@ -100,7 +130,7 @@ module Babushka
|
|
100
130
|
end
|
101
131
|
|
102
132
|
def chooser
|
103
|
-
|
133
|
+
Babushka.host.match_list
|
104
134
|
end
|
105
135
|
|
106
136
|
def chooser_choices
|
data/lib/babushka/dep_pool.rb
CHANGED
@@ -9,36 +9,33 @@ module Babushka
|
|
9
9
|
def count
|
10
10
|
@pool.length
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def names
|
14
14
|
@pool.keys
|
15
15
|
end
|
16
|
+
|
16
17
|
def items
|
17
18
|
@pool.values
|
18
19
|
end
|
20
|
+
|
19
21
|
def for spec
|
20
22
|
spec.respond_to?(:name) ? @pool[spec.name] : @pool[spec]
|
21
23
|
end
|
22
24
|
|
23
25
|
def add_dep name, params, block
|
24
|
-
|
25
|
-
self.for name
|
26
|
-
else
|
26
|
+
self.for(name) || begin
|
27
27
|
opts = params.extract_options!
|
28
28
|
Dep.new name, @source, params, opts, block
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
def add_template name, in_opts, block
|
33
|
-
|
33
|
+
DepTemplate.for name, @source, in_opts, &block
|
34
34
|
end
|
35
35
|
|
36
36
|
def clear!
|
37
37
|
@pool = {}
|
38
38
|
end
|
39
|
-
def uncache!
|
40
|
-
items.each {|i| i.send :uncache! }
|
41
|
-
end
|
42
39
|
|
43
40
|
def register item
|
44
41
|
raise "Already registered '#{item.name}'." if @pool.has_key?(item.name)
|
@@ -1,5 +1,24 @@
|
|
1
1
|
module Babushka
|
2
|
-
|
2
|
+
# A BaseTemplate is just a blank, passthrough template -- all it does is
|
3
|
+
# return DepContext as the context against which standard (i.e. untemplated)
|
4
|
+
# deps are defined.
|
5
|
+
class BaseTemplate
|
6
|
+
def self.contextual_name; name end
|
7
|
+
def self.suffixed?; false end
|
8
|
+
def self.context_class; DepContext end
|
9
|
+
end
|
10
|
+
|
11
|
+
# This class represents a template against which deps can be defined. The
|
12
|
+
# resulting deps are structured just like regular ones, except for the context
|
13
|
+
# against which they were defined.
|
14
|
+
#
|
15
|
+
# Standard deps are defined against DepContext, which makes just the basic dep
|
16
|
+
# DSL available, i.e. requires/met?/meet, etc. Templated deps are defined against
|
17
|
+
# a subclass of TemplatedDepContext as built by +build_context+.
|
18
|
+
#
|
19
|
+
# This means that when a templated dep is defined, the context will be a superset
|
20
|
+
# of that of a standard dep -- the normal stuff, plus whatever the template adds.
|
21
|
+
class DepTemplate
|
3
22
|
include LogHelpers
|
4
23
|
|
5
24
|
INVALID_NAMES = %w[base]
|
@@ -54,7 +73,7 @@ module Babushka
|
|
54
73
|
end
|
55
74
|
|
56
75
|
def build_context block
|
57
|
-
Class.new(
|
76
|
+
Class.new(TemplatedDepContext, &block).tap {|context|
|
58
77
|
shadow = self
|
59
78
|
context.metaclass.send :define_method, :source_template do
|
60
79
|
shadow
|
data/lib/babushka/dsl.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
module Babushka
|
2
2
|
module DSL
|
3
|
+
# Make these helpers directly callable, and private when included.
|
4
|
+
module_function
|
5
|
+
|
3
6
|
# Use +spec+ to look up a dep. Because +spec+ might include a source
|
4
7
|
# prefix, the dep this method returns could be from any of the currently
|
5
8
|
# known sources.
|
data/lib/babushka/git_repo.rb
CHANGED
@@ -3,67 +3,74 @@ module Babushka
|
|
3
3
|
end
|
4
4
|
class GitRepoExists < GitRepoError
|
5
5
|
end
|
6
|
-
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
6
|
+
|
7
|
+
# Provides some wrapper methods for interacting concisely with a git
|
8
|
+
# repository.
|
9
|
+
#
|
10
|
+
# The repo is accessed by shelling out to `git` via the {repo_shell}
|
11
|
+
# method, which makes sure the repo exists and that the commands are run
|
12
|
+
# in the right place. Hence, GitRepo doesn't depend on your current
|
13
|
+
# working directory.
|
14
|
+
#
|
15
|
+
# Most of the methods return a boolean and are used to discover things
|
16
|
+
# about the repository, like whether it's {clean?} or {dirty?}, currently
|
17
|
+
# {merging?} or {rebasing?}, and whether it's {ahead?} or {behind?} the
|
18
|
+
# default remote.
|
11
19
|
#
|
12
|
-
#
|
20
|
+
# Some return a piece of data, like {current_head} and {current_branch}.
|
13
21
|
#
|
14
|
-
#
|
22
|
+
# There are also some methods that make simple changes to the repository,
|
23
|
+
# like {checkout!} and {reset_hard!}.
|
15
24
|
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
# * {#include?} ref
|
19
|
-
# * {#ahead?}
|
20
|
-
# * {#behind?}
|
21
|
-
# * {#rebasing?}
|
22
|
-
# * {#applying?}
|
23
|
-
# * {#merging?}
|
24
|
-
# * {#bisecting?}
|
25
|
-
# * {#rebase_merging?}
|
26
|
-
# * {#rebasing_interactively?}
|
25
|
+
# To perform other operations on the repository like committing or
|
26
|
+
# rebasing, check out grit. This class is just a little `git` wrapper.
|
27
27
|
#
|
28
|
-
# Methods for repository operations:
|
29
|
-
#
|
30
|
-
# * {#clone!}
|
31
|
-
# * {#branch!}
|
32
|
-
# * {#track!}
|
33
|
-
# * {#checkout!}
|
34
|
-
# * {#reset_hard!} refspec
|
35
|
-
|
36
28
|
class GitRepo
|
37
29
|
include ShellHelpers
|
38
30
|
extend ShellHelpers
|
39
31
|
|
32
|
+
attr_reader :path
|
33
|
+
|
34
|
+
# The full path to the root of the repo {path} is within, if it is within
|
35
|
+
# one somewhere; otherwise nil.
|
40
36
|
def self.repo_for path
|
41
|
-
maybe = shell("git rev-parse --git-dir", :cd => path) if path.p.dir?
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
37
|
+
maybe = shell?("git rev-parse --git-dir", :cd => path) if path.p.dir?
|
38
|
+
|
39
|
+
if maybe == '.git'
|
40
|
+
path.p
|
41
|
+
elsif !maybe.nil?
|
42
|
+
maybe / '..'
|
43
|
+
end
|
48
44
|
end
|
49
45
|
|
50
|
-
def path
|
51
|
-
@path
|
46
|
+
def initialize path
|
47
|
+
@path = path.p
|
52
48
|
end
|
53
49
|
|
50
|
+
# This repo's top-level directory.
|
54
51
|
def root
|
55
52
|
@root ||= self.class.repo_for(path)
|
56
53
|
end
|
57
54
|
|
55
|
+
# This repo's +.git+ directory, where git stores its objects and other repo data.
|
58
56
|
def git_dir
|
59
57
|
root / '.git'
|
60
58
|
end
|
61
59
|
|
60
|
+
# True if +root+ points to an existing git repo.
|
61
|
+
#
|
62
|
+
# The repo doesn't always have to exist. For example, you can pass a
|
63
|
+
# nonexistent path when you initialize a GitRepo, and then call {clone!}
|
64
|
+
# on it.
|
62
65
|
def exists?
|
63
66
|
!root.nil? && root.exists?
|
64
67
|
end
|
65
|
-
|
68
|
+
|
69
|
+
# Run +cmd+ on the shell, changing to this repo's {root}. If the repo
|
70
|
+
# doesn't exist, a GitRepoError is raised.
|
66
71
|
#
|
72
|
+
# A GitRepo with a nonexistent {root} is valid - it will only fail if
|
73
|
+
# an operation that requires an existing repo is attempted.
|
67
74
|
def repo_shell cmd, opts = {}, &block
|
68
75
|
if !exists?
|
69
76
|
raise GitRepoError, "There is no repo at #{@path}."
|
@@ -72,45 +79,75 @@ module Babushka
|
|
72
79
|
end
|
73
80
|
end
|
74
81
|
|
82
|
+
def repo_shell? cmd, opts = {}
|
83
|
+
if !exists?
|
84
|
+
raise GitRepoError, "There is no repo at #{@path}."
|
85
|
+
else
|
86
|
+
shell? cmd, opts.merge(:cd => root)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
# True if the repo is clean, i.e. when the content in its index and working
|
92
|
+
# copy match the commit that HEAD refers to.
|
75
93
|
def clean?
|
76
94
|
repo_shell("git status") # Sometimes git caches invalid index info; this clears it.
|
77
95
|
repo_shell("git diff-index --name-status HEAD", &:stdout).blank?
|
78
96
|
end
|
79
97
|
|
98
|
+
# The inverse of {clean?} -- true if the content in the repo's index or
|
99
|
+
# working copy differs from the commit HEAD refers to.
|
80
100
|
def dirty?
|
81
101
|
!clean?
|
82
102
|
end
|
83
103
|
|
104
|
+
# True if the commit referenced by +ref+ is present somewhere in this repo.
|
105
|
+
#
|
106
|
+
# Note that the ref being present doesn't mean that it's a parent of +HEAD+,
|
107
|
+
# just that it currently resolves to a commit.
|
84
108
|
def include? ref
|
85
109
|
repo_shell("git rev-list -n 1 '#{ref}'")
|
86
110
|
end
|
87
111
|
|
112
|
+
# True if there are any commits in the current branch's history that
|
113
|
+
# aren't also present on the corresponding remote branch, or if the
|
114
|
+
# remote doesn't exist.
|
88
115
|
def ahead?
|
89
116
|
!remote_branch_exists? ||
|
90
|
-
!repo_shell("git rev-list
|
117
|
+
!repo_shell("git rev-list #{current_remote_branch}..").split("\n").empty?
|
91
118
|
end
|
92
119
|
|
120
|
+
# True if there are any commits in the current branch's corresponding remote
|
121
|
+
# branch that aren't also present locally, if the remote branch exists.
|
93
122
|
def behind?
|
94
123
|
remote_branch_exists? &&
|
95
|
-
!repo_shell("git rev-list
|
124
|
+
!repo_shell("git rev-list ..#{current_remote_branch}").split("\n").empty?
|
96
125
|
end
|
97
126
|
|
127
|
+
# True if the repo is partway through a rebase of some kind. This could be
|
128
|
+
# because one of the commits conflicted when it was replayed, or that the
|
129
|
+
# rebase is interactive and is awaiting another command.
|
98
130
|
def rebasing?
|
99
131
|
%w[rebase rebase-apply ../.dotest].any? {|d|
|
100
132
|
(git_dir / d).exists?
|
101
133
|
} or rebase_merging? or rebasing_interactively?
|
102
134
|
end
|
103
135
|
|
136
|
+
# True if a patch is partway through being applied -- perhaps because applying
|
137
|
+
# it caused conflicts that are yet to be resolved.
|
104
138
|
def applying?
|
105
139
|
%w[rebase rebase-apply ../.dotest].any? {|d|
|
106
140
|
(git_dir / d / 'applying').exists?
|
107
141
|
}
|
108
142
|
end
|
109
143
|
|
144
|
+
# True if a merge is in progress -- perhaps because it produced conflicts that
|
145
|
+
# are yet to be resolved.
|
110
146
|
def merging?
|
111
147
|
(git_dir / 'MERGE_HEAD').exists? or rebase_merging?
|
112
148
|
end
|
113
149
|
|
150
|
+
# True if a bisect is currently in progress.
|
114
151
|
def bisecting?
|
115
152
|
(git_dir / 'BISECT_LOG').exists?
|
116
153
|
end
|
@@ -127,28 +164,70 @@ module Babushka
|
|
127
164
|
}
|
128
165
|
end
|
129
166
|
|
167
|
+
|
168
|
+
|
169
|
+
# An array of the names of all the local branches in this repo.
|
130
170
|
def branches
|
131
|
-
repo_shell('git branch').split("\n").map {|l| l.sub(/^[* ]+/, '') }
|
171
|
+
names = repo_shell('git branch').split("\n").map {|l| l.sub(/^[* ]+/, '') }
|
172
|
+
names - ['(no branch)']
|
132
173
|
end
|
133
174
|
|
175
|
+
def all_branches
|
176
|
+
names = repo_shell('git branch -a').split("\n").map {|l| l.sub(/^[* ]+/, '') }
|
177
|
+
(names - ['(no branch)']).reject {|i|
|
178
|
+
i['/origin/HEAD ->']
|
179
|
+
}.map {|i|
|
180
|
+
i.sub(/^remotes\//, '')
|
181
|
+
}
|
182
|
+
end
|
183
|
+
|
184
|
+
# The name of the branch that's currently checked out, if any. If there
|
185
|
+
# is no current branch (i.e. if the HEAD is detached), the HEAD's SHA is
|
186
|
+
# returned instead.
|
134
187
|
def current_branch
|
135
188
|
repo_shell("cat .git/HEAD").strip.sub(/^.*refs\/heads\//, '')
|
136
189
|
end
|
137
190
|
|
191
|
+
# The namespaced name of the remote branch that the current local branch
|
192
|
+
# is tracking, or on origin if the branch isn't tracking an explicit
|
193
|
+
# remote branch.
|
194
|
+
def current_remote_branch
|
195
|
+
branch = current_branch
|
196
|
+
"#{remote_for(branch)}/#{branch}"
|
197
|
+
end
|
198
|
+
|
199
|
+
# The short SHA of the repo's current HEAD. This is usually 7 characters,
|
200
|
+
# but is longer when extra characters are required to disambiguate it.
|
138
201
|
def current_head
|
139
202
|
repo_shell("git rev-parse --short HEAD")
|
140
203
|
end
|
141
204
|
|
205
|
+
# The full 40 character SHA of the current HEAD.
|
142
206
|
def current_full_head
|
143
207
|
repo_shell("git rev-parse HEAD")
|
144
208
|
end
|
145
209
|
|
210
|
+
# The short SHA of the commit that +ref+ currently refers to.
|
211
|
+
def resolve ref
|
212
|
+
repo_shell?("git rev-parse --short #{ref}")
|
213
|
+
end
|
214
|
+
|
215
|
+
# The remote assigned to branch in the git config, or 'origin' if none
|
216
|
+
# is set. This is the remote that git pushes to and fetches from for this
|
217
|
+
# branch by default, and the branch that comparisons like #ahead? and
|
218
|
+
# #behind? are made against.
|
219
|
+
def remote_for branch
|
220
|
+
repo_shell?("git config branch.#{branch}.remote") || 'origin'
|
221
|
+
end
|
222
|
+
|
223
|
+
# True if origin contains a branch of the same name as the current local
|
224
|
+
# branch.
|
146
225
|
def remote_branch_exists?
|
147
|
-
repo_shell(
|
148
|
-
b[/^(remotes\/)?origin\/#{current_branch}$/]
|
149
|
-
}
|
226
|
+
repo_shell?("git rev-parse refs/remotes/#{current_remote_branch}")
|
150
227
|
end
|
151
228
|
|
229
|
+
# Clone the remote at +from+ to this GitRepo's path. The path must be
|
230
|
+
# nonexistent; an error is raised if the local repo already exists.
|
152
231
|
def clone! from
|
153
232
|
raise GitRepoExists, "Can't clone #{from} to existing path #{path}." if exists?
|
154
233
|
shell("git clone '#{from}' '#{path.basename}'", :cd => path.parent, :create => true) {|shell|
|
@@ -156,20 +235,35 @@ module Babushka
|
|
156
235
|
}
|
157
236
|
end
|
158
237
|
|
159
|
-
|
160
|
-
|
238
|
+
# Create a new local branch called +branch+ with +ref+ (defaulting to
|
239
|
+
# HEAD) as its tip.
|
240
|
+
def branch! branch, ref = 'HEAD'
|
241
|
+
repo_shell("git branch '#{branch}' '#{ref}'")
|
161
242
|
end
|
162
243
|
|
244
|
+
# Create a new local tracking branch for +branch+, which should be specified
|
245
|
+
# as remote/branch. For example, if "origin/next" is passed, a local 'next'
|
246
|
+
# branch will be created to track origin's 'next' branch.
|
163
247
|
def track! branch
|
164
|
-
repo_shell("git checkout -t '#{branch}'")
|
248
|
+
repo_shell("git checkout -t '#{branch}' -b '#{branch.sub(/^.*\//, '')}'")
|
249
|
+
end
|
250
|
+
|
251
|
+
# Check out the supplied ref, detaching the HEAD if the named ref
|
252
|
+
# isn't a branch.
|
253
|
+
def checkout! ref
|
254
|
+
repo_shell("git checkout '#{ref}'")
|
165
255
|
end
|
166
256
|
|
167
|
-
|
168
|
-
|
257
|
+
# Check out the supplied ref, detaching the HEAD. If the ref is a branch
|
258
|
+
# or tag, HEAD will reference the commit at the tip of the ref.
|
259
|
+
def detach! ref = 'HEAD'
|
260
|
+
repo_shell("git checkout '#{resolve(ref)}'")
|
169
261
|
end
|
170
262
|
|
171
|
-
|
172
|
-
|
263
|
+
# Reset the repo to the given ref, discarding changes in the index and
|
264
|
+
# working copy.
|
265
|
+
def reset_hard! ref = 'HEAD'
|
266
|
+
repo_shell("git reset --hard '#{ref}'")
|
173
267
|
end
|
174
268
|
|
175
269
|
def inspect
|