Module: GitRemoteBranch

Includes:
CaptureFu
Defined in:
lib/state.rb,
lib/version.rb,
lib/constants.rb,
lib/param_reader.rb,
lib/git_remote_branch.rb

Defined Under Namespace

Modules: VERSION Classes: InvalidBranchError, NotOnGitRepositoryError

Constant Summary collapse

NAME =
'git_remote_branch'
COMPLETE_NAME =
"#{NAME} #{VERSION::STRING}"
COMMAND_NAME =
'grb'
SHORT_NAME =
COMMAND_NAME
GIT =
(ENV['GRB_GIT'] || 'git')
LOCAL_BRANCH_LISTING_COMMAND =
"#{GIT} branch -l"
COMMANDS =
{
  :create     => {
    :description => 'create a new remote branch and track it locally',
    :aliases  => %w{create new},
    :commands => [
      '"#{GIT} push #{origin} #{current_branch}:refs/heads/#{branch_name}"',
      '"#{GIT} fetch #{origin}"',
      '"#{GIT} branch --track #{branch_name} #{origin}/#{branch_name}"',
      '"#{GIT} checkout #{branch_name}"'
    ]
  },

  :publish     => {
    :description => 'publish an existing local branch',
    :aliases  => %w{publish remotize share},
    :commands => [
      '"#{GIT} push #{origin} #{branch_name}:refs/heads/#{branch_name}"',
      '"#{GIT} fetch #{origin}"',
      '"#{GIT} branch --set-upstream #{branch_name} #{origin}/#{branch_name}"',
      '"#{GIT} checkout #{branch_name}"'
    ]
  },

  :rename     => {
    :description => 'rename a remote branch and its local tracking branch',
    :aliases  => %w{rename rn mv move},
    :commands => [
      '"#{GIT} push #{origin} #{current_branch}:refs/heads/#{branch_name}"',
      '"#{GIT} fetch #{origin}"',
      '"#{GIT} branch --track #{branch_name} #{origin}/#{branch_name}"',
      '"#{GIT} checkout #{branch_name}"',
      '"#{GIT} push #{origin} :refs/heads/#{current_branch}"',
      '"#{GIT} branch -d #{current_branch}"',
    ]
  },

  :delete     => {
    :description => 'delete a local and a remote branch',
    :aliases  => %w{delete destroy kill remove rm},
    :commands => [
      '"#{GIT} push #{origin} :refs/heads/#{branch_name}"',
      '"#{GIT} checkout master" if current_branch == branch_name',
      '"#{GIT} branch -d #{branch_name}"'
    ]
  },

  :track      => {
    :description => 'track an existing remote branch',
    :aliases  => %w{track follow grab fetch},
    :commands => [
      '"#{GIT} fetch #{origin}"',
      '"#{GIT} branch --set-upstream #{branch_name} #{origin}/#{branch_name}"'
    ]
  }
}
ALIAS_REVERSE_MAP =
get_reverse_map(COMMANDS)

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.get_reverse_map(commands) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/git_remote_branch.rb', line 78

def self.get_reverse_map(commands)
  h={}
  commands.each_pair do |cmd, params|
    params[:aliases].each do |alias_|
      unless h[alias_]
        h[alias_] = cmd
      else
        raise "Duplicate aliases: #{alias_.inspect} already defined for command #{h[alias_].inspect}"
      end
    end
  end
  h
end

Instance Method Details

#execute_action(action, branch_name, origin, current_branch) ⇒ Object



121
122
123
124
# File 'lib/git_remote_branch.rb', line 121

def execute_action(action, branch_name, origin, current_branch)
  cmds = COMMANDS[action][:commands].map{ |c| eval(c) }.compact
  execute_cmds(cmds)
end

#execute_cmds(*cmds) ⇒ Object



134
135
136
137
138
139
140
141
# File 'lib/git_remote_branch.rb', line 134

def execute_cmds(*cmds)
  silencer = $WHISPER ? ' 2>&1' : ''
  cmds.flatten.each do |c|
    puts_cmd c
    `#{c}#{silencer}`
    whisper ''
  end
end

#explain_action(action, branch_name, origin, current_branch) ⇒ Object



126
127
128
129
130
131
132
# File 'lib/git_remote_branch.rb', line 126

def explain_action(action, branch_name, origin, current_branch)
  cmds = COMMANDS[action][:commands].map{ |c| eval(c) }.compact

  whisper "List of operations to do to #{COMMANDS[action][:description]}:", ''
  puts_cmd cmds
  whisper ''
end

#explain_mode!(argv) ⇒ Object



39
40
41
42
43
44
45
46
# File 'lib/param_reader.rb', line 39

def explain_mode!(argv)
  if argv[0].to_s.downcase == 'explain'
    argv.shift
    true
  else
    false
  end
end

#get_action(action) ⇒ Object



52
53
54
# File 'lib/param_reader.rb', line 52

def get_action(action)
  ALIAS_REVERSE_MAP[action.to_s.downcase]
end

#get_branch(branch) ⇒ Object



56
57
58
# File 'lib/param_reader.rb', line 56

def get_branch(branch)
  branch
end

#get_current_branchObject



5
6
7
# File 'lib/state.rb', line 5

def get_current_branch
  local_branch_information[0]
end

#get_origin(origin) ⇒ Object



60
61
62
# File 'lib/param_reader.rb', line 60

def get_origin(origin)
  return origin || 'origin'
end

#get_usageObject



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/git_remote_branch.rb', line 97

def get_usage
  return <<-HELP
Usage:

#{[:create, :publish, :rename, :delete, :track].map{|action|
    "  grb #{action} branch_name [origin_server]"
  } * "\n"
}

Notes:
- If origin_server is not specified, the name 'origin' is assumed (git's default)
- The rename functionality renames the current branch

The explain meta-command: you can also prepend any command with the keyword 'explain'. Instead of executing the command, git_remote_branch will simply output the list of commands you need to run to accomplish that goal.
Example:
  grb explain create
  grb explain create my_branch github

All commands also have aliases:
#{ COMMANDS.keys.map{|k| k.to_s}.sort.map {|cmd| 
  "#{cmd}: #{COMMANDS[cmd.to_sym][:aliases].join(', ')}" }.join("\n  ") }
HELP
end

#get_welcomeObject



93
94
95
# File 'lib/git_remote_branch.rb', line 93

def get_welcome
  "git_remote_branch version #{VERSION::STRING}\n\n"
end

#git_found?Boolean

Returns:

  • (Boolean)


13
14
15
16
17
18
# File 'lib/state.rb', line 13

def git_found?
  ret, msg = capture_process_output "#{GIT} --version"
  user_version = msg.chomp.split[2]
  warn "Some grb commands will not work with git version < 1.7 (you have #{user_version})" unless user_version >= '1.7'
  ret == 0
end

#local_branchesObject



9
10
11
# File 'lib/state.rb', line 9

def local_branches
  local_branch_information[1]
end

#puts_cmd(*cmds) ⇒ Object



143
144
145
146
147
# File 'lib/git_remote_branch.rb', line 143

def puts_cmd(*cmds)
  cmds.flatten.each do |c|
    whisper "#{c}".foreground(:red)
  end
end

#read_params(argv) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/param_reader.rb', line 7

def read_params(argv)
  #TODO Some validation on the params

  p={}
  p[:silent]  = silent!(argv)
  p[:explain] = explain_mode!(argv)

  p[:action]  = get_action(argv[0]) or return HELP_PARAMS

  return HELP_PARAMS if p[:action] == :help

  p[:branch]  = get_branch(argv[1])
  p[:origin]  = get_origin(argv[2])

  # If in explain mode, the user doesn't have to specify a branch or be on in
  # actual repo to get the explanation.
  # Of course if he is, the explanation will be made better by using contextual info.
  if p[:explain]
    p[:branch] ||= "branch_to_#{p[:action]}"
    p[:current_branch] = begin
      get_current_branch
    rescue NotOnGitRepositoryError, InvalidBranchError
      'current_branch'
    end

  else
    return HELP_PARAMS unless p[:branch]
    p[:current_branch] = get_current_branch
  end
  return p
end

#silent!(argv) ⇒ Object



48
49
50
# File 'lib/param_reader.rb', line 48

def silent!(argv)
  !!argv.delete('--silent')
end