Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented Branch Checkout (#141) #189

Open
wants to merge 3 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions autoload/magit/git.vim
Original file line number Diff line number Diff line change
Expand Up @@ -339,3 +339,9 @@ function! magit#git#get_remote_branch(ref, type)
return "none"
endtry
endfunction


function! magit#git#get_branches()
return magit#sys#system(g:magit_git_cmd . " branch -a")
endfunction

18 changes: 18 additions & 0 deletions autoload/magit/mapping.vim
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ let g:magit_commit_fixup_mapping = get(g:, 'magit_commit_fixup_mapping',
let g:magit_close_commit_mapping = get(g:, 'magit_close_commit_mapping', 'CU' )
let g:magit_reload_mapping = get(g:, 'magit_reload_mapping', 'R' )
let g:magit_edit_mapping = get(g:, 'magit_edit_mapping', 'E' )
let g:magit_checkout_mapping = get(g:, 'magit_checkout_mapping', 'CBB')
let g:magit_checkout_last_mapping = get(g:, 'magit_checkout_last_mapping', 'CB-')
let g:magit_checkout_force_mapping = get(g:, 'magit_checkout_force_mapping', 'CBF')

let g:magit_jump_next_hunk = get(g:, 'magit_jump_next_hunk', '<C-N>')
let g:magit_jump_prev_hunk = get(g:, 'magit_jump_prev_hunk', '<C-P>')
Expand Down Expand Up @@ -157,6 +160,13 @@ function! magit#mapping#set_default()
call s:mg_set_mapping('n', g:magit_jump_prev_hunk,
\ "magit#jump_hunk('P')")

call s:mg_set_mapping('n', g:magit_checkout_mapping,
\ "magit#checkout_branch('B')")
call s:mg_set_mapping('n', g:magit_checkout_last_mapping,
\ "magit#checkout_branch('-')")
call s:mg_set_mapping('n', g:magit_checkout_force_mapping,
\ "magit#checkout_branch('F')")

for mapping in g:magit_folding_toggle_mapping
" trick to pass '<cr>' in a mapping command without being interpreted
let func_arg = ( mapping ==? "<cr>" ) ? '+' : mapping
Expand Down Expand Up @@ -227,6 +237,14 @@ function! magit#mapping#set_default()
\' modifying the previous commit message',
\g:magit_close_commit_mapping
\. ' commit undo, cancel and close current commit message',
\g:magit_checkout_mapping
\. ' From stage mode: set branch mode in normal flavor',
\' From branch mode: checkout branch on line cursor is on.',
\g:magit_checkout_force_mapping
\. ' From stage mode: set branch mode in force flavor',
\' From branch mode: checkout/reset branch on line cursor is on.',
\g:magit_checkout_last_mapping
\. ' From stage mode: checkout previous branch.',
\g:magit_reload_mapping
\.' refresh magit buffer',
\g:magit_diff_shrink.','.g:magit_diff_enlarge.','.g:magit_diff_reset
Expand Down
3 changes: 2 additions & 1 deletion common/magit_common.vim
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ let g:magit_sections = {
\ 'staged': 'Staged changes',
\ 'unstaged': 'Unstaged changes',
\ 'commit': 'Commit message',
\ 'stash': 'Stash list'
\ 'stash': 'Stash list',
\ 'branches': 'Branch list'
\ }

let g:magit_section_info = {
Expand Down
34 changes: 33 additions & 1 deletion doc/vimagit.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,26 @@ Commit mode has two flavors.

By the way, you can also perform all stage mode actions in commit mode.

BRANCH MODE *vimagit-branch-mode*

In this mode, the `Branch list` section is open, where you can choose any
existing local or remote branch as well as create a new local branch.
There are two flavors to Branch mode:

* `normal`: selected branch will be created/checked out normally.
* `force`: selected branch will be created if nonexistant, or reset if existant.

SECTIONS *vimagit-sections*

IMPORTANT: mappings can have different meanings regarding the cursor position.

There are 5 sections:
There are 6 sections:
* Info: this section display some information about the git repository, like
the current branch and the HEAD commit.
* Commit message: this section appears in commit mode (see below). It contains
the message to be committed.
* Branch list: this section contains all of the current local and remote
brances.
* Staged changes: this sections contains all staged files/hunks, ready to
commit.
* Unstaged changes: this section contains all unstaged and untracked
Expand Down Expand Up @@ -218,6 +229,27 @@ section only.



*vimagit-CBB* *magit#checkout_branch('B')*
*vimagit-g:magit_checkout_mapping*
<CBB> From `stage mode`, set branch mode in `normal` flavor and show
"Branches" section. When used in `branch mode`, the branch name on
the line the cursor is on will be checked out. Created locally if
needed. This is equivalent to `git checkout -b <branch> [remote]`

*vimagit-CBF* *magit#checkout_branch('F')*
*vimagit-g:magit_checkout_force_mapping*
<CBF> From `stage mode` or `branch mode`, set branching to `force` mode,
and checkout any new or existing branches with <CBF> while the cursor
is on the line of the desired branch. This is equivalent to
`git checkout -B <branch> [remote]`.

*vimagit-CB-* *magit#checkout_branch('-')*
*vimagit-g:magit_checkout_last_mapping*
<CB-> From `stage mode`, instantly checkout the previous branch. Any
changes are carried along the checkout. This is equivalent to
`git checkout -`.


*vimagit-<C-n>* *magit#jump_hunk()*
*vimagit-<C-p>*
*vimagit-g:magit_jump_next_hunk*
Expand Down
132 changes: 131 additions & 1 deletion plugin/magit.vim
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ let g:magit_default_show_all_files = get(g:, 'magit_default_show_all_files',
let g:magit_default_fold_level = get(g:, 'magit_default_fold_level', 1)
let g:magit_auto_close = get(g:, 'magit_auto_close', 0)
let g:magit_auto_foldopen = get(g:, 'magit_auto_foldopen', 1)
let g:magit_default_sections = get(g:, 'magit_default_sections', ['info', 'global_help', 'commit', 'staged', 'unstaged'])
let g:magit_default_sections = get(g:, 'magit_default_sections', ['info', 'global_help', 'branch', 'commit', 'staged', 'unstaged'])
let g:magit_discard_untracked_do_delete = get(g:, 'magit_discard_untracked_do_delete', 0)

let g:magit_refresh_gutter = get(g:, 'magit_refresh_gutter' , 1)
Expand Down Expand Up @@ -249,6 +249,25 @@ function! s:mg_get_commit_section()
endif
endfunction

" s:mg_get_branches_section: this function writes in current buffer the branch
" section.
" WARNING: this function writes in file, it should only be called through
" protected functions like magit#update_buffer
" param[in] b:magit_show_branches:
function! s:mg_get_branches_section()
if ( b:magit_show_branches == 1 )
silent put =g:magit_sections.branches
silent put =magit#utils#underline(g:magit_sections.branches)

let branch_list = magit#git#get_branches()
silent put ='*Close*'
silent put ='New Branch:'
silent put =branch_list
silent put =''
silent put =''
endif
endfunction

" s:mg_search_block: helper function, to get start and end line of a block,
" giving a start and multiple end pattern
" a "pattern parameter" is a List:
Expand Down Expand Up @@ -390,6 +409,42 @@ function! s:mg_git_commit(mode) abort
let b:magit_just_commited = 1
endfunction

" s:mg_git_checkout_branch: checks out a branch (local or remote)
" param[in]: branch_name specifies the name of the branch
" remote specifies the name of the remote
" = '' specifies a local branch
" return none
function! s:mg_git_checkout_branch(branch_name, remote)
" Update the name of the remote branch (format: 'origin/master')
if ( a:remote != '' )
let remote_name = " " . a:remote . "/" . a:branch_name
endif

if ( b:magit_current_checkout_flag == 'B' && a:remote != '' )
let checkout_cmd = g:magit_git_cmd . " checkout -b " .
\ a:branch_name . " " . remote_name
elseif ( b:magit_current_checkout_flag == 'B' && b:magit_creating_new_branch == 1)
let checkout_cmd = g:magit_git_cmd . " checkout -b " .
\ a:branch_name
elseif ( b:magit_current_checkout_flag == 'B' || b:magit_current_checkout_flag == '-' )
let checkout_cmd = g:magit_git_cmd . " checkout " .
\ a:branch_name
elseif ( b:magit_current_checkout_flag == 'F' && a:remote != '' && b:magit_creating_new_branch == 0 )
let checkout_cmd = g:magit_git_cmd . " checkout -B " .
\ a:branch_name . remote_name
elseif ( b:magit_current_checkout_flag == 'F' && b:magit_creating_new_branch == 1 )
let checkout_cmd = g:magit_git_cmd . " checkout -B " .
\ a:branch_name
endif

try
silent! let git_result = magit#sys#system(checkout_cmd)
catch 'shell error'
call magit#sys#print_shell_error()
echoerr "Could not checkout branch ''" . a:branch_name . "'"
endtry
endfunction

" s:mg_select_file_block: select the whole diff file, relative to the current
" cursor position
" nota: if the cursor is not in a diff file when the function is called, this
Expand Down Expand Up @@ -531,6 +586,7 @@ let g:magit_last_updated_buffer = ''
let s:mg_display_functions = {
\ 'info': { 'fn': function("s:mg_get_info"), 'arg': []},
\ 'global_help': { 'fn': function("magit#mapping#get_section_help"), 'arg': ['global']},
\ 'branch': { 'fn': function("s:mg_get_branches_section"), 'arg': []},
\ 'commit': { 'fn': function("s:mg_get_commit_section"), 'arg': []},
\ 'staged': { 'fn': function("s:mg_get_staged_section"), 'arg': ['staged']},
\ 'unstaged': { 'fn': function("s:mg_get_staged_section"), 'arg': ['unstaged']},
Expand Down Expand Up @@ -851,6 +907,9 @@ function! magit#show_magit(display, ...)
let b:magit_current_commit_mode=''
let b:magit_commit_newly_open=0

let b:magit_show_branches=0
let b:magit_current_branch_mode=''

let b:magit_diff_context=3

let b:magit_just_commited = 0
Expand Down Expand Up @@ -1273,6 +1332,73 @@ function! magit#jump_hunk(dir)
endif
endfunction

" magit#checkout_branch: entry function for branch checkout
" param[in]: opt specifies the option for checkout
" 'B' is for '-b'
" 'F' is for '-B'
" '-' is to checkout previous branch
function! magit#checkout_branch(opt)
let b:magit_current_checkout_flag = a:opt
if ( b:magit_show_branches == 0 && a:opt != '-' )
let b:magit_show_branches = 1
else
call magit#select_branch()
endif

if ( a:opt == '-' )
call <SID>mg_git_checkout_branch('-', '')
endif

call magit#update_buffer()
endfunction

" magit#select_branch: handles the parsing and passing of the selected branch
" return no
function! magit#select_branch()
let line = trim(getline("."))

" cannot checkout HEAD
if ( match(line, "HEAD") != -1 )
let b:magit_show_branches = 0
call magit#update_buffer()
return
endif

" close buffer if requested
if ( match(line, "*Close*") != -1 )
let b:magit_show_branches = 0
call magit#update_buffer()
return
endif

" check whether attempting to checkout remote branch
" and pass to s:mg_git_checkout_branch() with correct + clean options
let is_remote = match(line, "remotes")
if ( is_remote != -1 )
let line = substitute(line, "^remotes/", "", "")
let remote = matchstr(line, "[^/]*")
let branch = matchstr(line, ".*", len(remote)+1)
call <SID>mg_git_checkout_branch(branch, remote)
else
" disregard if attempting to checkout current branch
if ( match(line, "*") != -1 )
echo "You are already checked out on this branch..."
return
else
" handle custom input for new branch
if ( match(line, "^New Branch:") != -1 )
let anti_line = matchstr(line, "[^:]*")
let line = trim(matchstr(line, ".*", len(anti_line)+1))
let b:magit_creating_new_branch = 1
else
let b:magit_creating_new_branch = 0
endif

call <SID>mg_git_checkout_branch(line, '')
endif
endif
endfunction

" magit#get_staged_files: function returning an array with staged files names
" return: an array with staged files names
function! magit#get_staged_files()
Expand Down Expand Up @@ -1348,6 +1474,10 @@ function! magit#get_current_mode()
return "COMMIT"
elseif ( b:magit_current_commit_mode == 'CA' )
return "AMEND"
elseif ( b:magit_current_checkout_flag == 'B' )
return "BRANCH"
elseif ( b:magit_current_checkout_flag == 'F' )
return "FORCE"
endif
endfunction

Expand Down