[
  {
    "path": ".gitattributes",
    "content": ".git* export-ignore\n*.markdown export-ignore\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "github: tpope\ncustom: [\"https://www.paypal.me/vimpope\"]\n"
  },
  {
    "path": ".gitignore",
    "content": "/doc/tags\n"
  },
  {
    "path": "CONTRIBUTING.markdown",
    "content": "Before reporting a bug, you should try stripping down your Vim configuration\nand removing other plugins.  The sad truth about VimScript is that it is\nfraught with incompatibilities waiting to happen.  I'm happy to work around\nthem where I can, but it's up to you to isolate the conflict.\n\nFugitive is particularly prone to regressions due to Git version issues,\nplatform issues, and interactions with other plugins.  I end up bisecting a\nlot more than other projects, and thus I'm especially meticulous here about\nmaintaining a clean, readable, history.  Squash and force push any requested\nchanges to a pull request.  And if your [commit message\nsucks](https://commit.style), I'm not going to accept it.  Period.\n\nIf your contribution involves adding a configuration option, you are going to\nneed a very compelling justification for it.  Options add a maintenance\nburden, support burden, and documentation bloat, and oftentimes can be\nachieved much more simply with a custom map or autocommand.  If your option\ncontrols an underlying Git command, ask yourself why Git itself does not offer\nsuch configuration.\n\nBeyond that, don't be shy about asking before patching.  What takes you hours\nmight take me minutes simply because I have both domain knowledge and a\nperverse knowledge of VimScript so vast that many would consider it a symptom\nof mental illness.  On the flip side, some ideas I'll reject no matter how\ngood the implementation is.  \"Send a patch\" is an edge case answer in my book.\n"
  },
  {
    "path": "README.markdown",
    "content": "# fugitive.vim\n\nFugitive is the premier Vim plugin for Git.  Or maybe it's the premier Git\nplugin for Vim?  Either way, it's \"so awesome, it should be illegal\".  That's\nwhy it's called Fugitive.\n\nThe crown jewel of Fugitive is `:Git` (or just `:G`), which calls any\narbitrary Git command.  If you know how to use Git at the command line, you\nknow how to use `:Git`.  It's vaguely akin to `:!git` but with numerous\nimprovements:\n\n* The default behavior is to directly echo the command's output.  Quiet\n  commands like `:Git add` avoid the dreaded \"Press ENTER or type command to\n  continue\" prompt.\n* `:Git commit`, `:Git rebase -i`, and other commands that invoke an editor do\n  their editing in the current Vim instance.\n* `:Git diff`, `:Git log`, and other verbose, paginated commands have their\n  output loaded into a temporary buffer.  Force this behavior for any command\n  with `:Git --paginate` or `:Git -p`.\n* `:Git blame` uses a temporary buffer with maps for additional triage.  Press\n  enter on a line to view the commit where the line changed, or `g?` to see\n  other available maps.  Omit the filename argument and the currently edited\n  file will be blamed in a vertical, scroll-bound split.\n* `:Git mergetool` and `:Git difftool` load their changesets into the quickfix\n  list.\n* Called with no arguments, `:Git` opens a summary window with dirty files and\n  unpushed and unpulled commits.  Press `g?` to bring up a list of maps for\n  numerous operations including diffing, staging, committing, rebasing, and\n  stashing.  (This is the successor to the old `:Gstatus`.)\n* This command (along with all other commands) always uses the current\n  buffer's repository, so you don't need to worry about the current working\n  directory.\n\nAdditional commands are provided for higher level operations:\n\n* View any blob, tree, commit, or tag in the repository with `:Gedit` (and\n  `:Gsplit`, etc.).  For example, `:Gedit HEAD~3:%` loads the current file as\n  it existed 3 commits ago.\n* `:Gdiffsplit` (or `:Gvdiffsplit`) brings up the staged version of the file\n  side by side with the working tree version.  Use Vim's diff handling\n  capabilities to apply changes to the staged version, and write that buffer\n  to stage the changes.  You can also give an arbitrary `:Gedit` argument to\n  diff against older versions of the file.\n* `:Gread` is a variant of `git checkout -- filename` that operates on the\n  buffer rather than the file itself.  This means you can use `u` to undo it\n  and you never get any warnings about the file changing outside Vim.\n* `:Gwrite` writes to both the work tree and index versions of a file, making\n  it like `git add` when called from a work tree file and like `git checkout`\n  when called from the index or a blob in history.\n* `:Ggrep` is `:grep` for `git grep`.  `:Glgrep` is `:lgrep` for the same.\n* `:GMove` does a `git mv` on the current file and changes the buffer name to\n  match.  `:GRename` does the same with a destination filename relative to the\n  current file's directory.\n* `:GDelete` does a `git rm` on the current file and simultaneously deletes\n  the buffer.  `:GRemove` does the same but leaves the (now empty) buffer\n  open.\n* `:GBrowse` to open the current file on the web front-end of your favorite\n  hosting provider, with optional line range (try it in visual mode).  Plugins\n  are available for popular providers such as [GitHub][rhubarb.vim],\n  [GitLab][fugitive-gitlab.vim], [Bitbucket][fubitive.vim],\n  [Gitee][fugitive-gitee.vim], [Pagure][pagure],\n  [Phabricator][vim-phabricator], [Azure DevOps][fugitive-azure-devops.vim],\n  and [sourcehut][srht.vim].\n\n[rhubarb.vim]: https://github.com/tpope/vim-rhubarb\n[fugitive-gitlab.vim]: https://github.com/shumphrey/fugitive-gitlab.vim\n[fubitive.vim]: https://github.com/tommcdo/vim-fubitive\n[fugitive-gitee.vim]: https://github.com/linuxsuren/fugitive-gitee.vim\n[pagure]: https://github.com/FrostyX/vim-fugitive-pagure\n[vim-phabricator]: https://github.com/jparise/vim-phabricator\n[fugitive-azure-devops.vim]: https://github.com/cedarbaum/fugitive-azure-devops.vim\n[srht.vim]: https://git.sr.ht/~willdurand/srht.vim\n\nAdd `%{FugitiveStatusline()}` to `'statusline'` to get an indicator\nwith the current branch in your statusline.\n\nFor more information, see `:help fugitive`.\n\n## Screencasts\n\n* [A complement to command line git](http://vimcasts.org/e/31)\n* [Working with the git index](http://vimcasts.org/e/32)\n* [Resolving merge conflicts with vimdiff](http://vimcasts.org/e/33)\n* [Browsing the git object database](http://vimcasts.org/e/34)\n* [Exploring the history of a git repository](http://vimcasts.org/e/35)\n\n## Installation\n\nInstall using your favorite package manager, or use Vim's built-in package\nsupport:\n\n    mkdir -p ~/.vim/pack/tpope/start\n    cd ~/.vim/pack/tpope/start\n    git clone https://tpope.io/vim/fugitive.git\n    vim -u NONE -c \"helptags fugitive/doc\" -c q\n\n## FAQ\n\n> What happened to the dispatch.vim backed asynchronous `:Gpush` and\n> `:Gfetch`?\n\nThis behavior was divisive, confusing, and complicated inputting passwords, so\nit was removed.  Use `:Git! push` to use Fugitive's own asynchronous\nexecution, or retroactively make `:Git push` asynchronous by pressing\n`CTRL-D`.\n\n> Why am I getting `core.worktree is required when using an external Git dir`?\n\nGit generally sets `core.worktree` for you automatically when necessary, but\nif you're doing something weird, or using a third-party tool that does\nsomething weird, you may need to set it manually:\n\n    git config core.worktree \"$PWD\"\n\nThis may be necessary even when simple `git` commands seem to work fine\nwithout it.\n\n> So I have a symlink and...\n\nStop.  Just stop.  If Git won't deal with your symlink, then Fugitive won't\neither.  Consider using a [plugin that resolves\nsymlinks](https://github.com/aymericbeaumet/symlink.vim), or even better,\nusing fewer symlinks.\n\n## Self-Promotion\n\nLike fugitive.vim? Follow the repository on\n[GitHub](https://github.com/tpope/vim-fugitive) and vote for it on\n[vim.org](http://www.vim.org/scripts/script.php?script_id=2975).  And if\nyou're feeling especially charitable, follow [tpope](http://tpo.pe/) on\n[Twitter](http://twitter.com/tpope) and\n[GitHub](https://github.com/tpope).\n\n## License\n\nCopyright (c) Tim Pope.  Distributed under the same terms as Vim itself.\nSee `:help license`.\n"
  },
  {
    "path": "autoload/fugitive.vim",
    "content": "\" Location:     autoload/fugitive.vim\n\" Maintainer:   Tim Pope <http://tpo.pe/>\n\n\" The functions contained within this file are for internal use only.  For the\n\" official API, see the commented functions in plugin/fugitive.vim.\n\n\" Section: Utility\n\nfunction! s:function(name) abort\n  return function(substitute(a:name,'^s:',matchstr(expand('<sfile>'), '.*\\zs<SNR>\\d\\+_'),''))\nendfunction\n\nfunction! s:sub(str,pat,rep) abort\n  return substitute(a:str,'\\v\\C'.a:pat,a:rep,'')\nendfunction\n\nfunction! s:gsub(str,pat,rep) abort\n  return substitute(a:str,'\\v\\C'.a:pat,a:rep,'g')\nendfunction\n\nfunction! s:Uniq(list) abort\n  let i = 0\n  let seen = {}\n  while i < len(a:list)\n    let str = string(a:list[i])\n    if has_key(seen, str)\n      call remove(a:list, i)\n    else\n      let seen[str] = 1\n      let i += 1\n    endif\n  endwhile\n  return a:list\nendfunction\n\nfunction! s:JoinChomp(list) abort\n  if empty(a:list[-1])\n    return join(a:list[0:-2], \"\\n\")\n  else\n    return join(a:list, \"\\n\")\n  endif\nendfunction\n\nfunction! s:winshell() abort\n  return has('win32') && &shellcmdflag !~# '^-'\nendfunction\n\nfunction! s:WinShellEsc(arg) abort\n  if type(a:arg) == type([])\n    return join(map(copy(a:arg), 's:WinShellEsc(v:val)'))\n  elseif a:arg =~# '^[A-Za-z0-9_/:.-]\\+$'\n    return a:arg\n  else\n    return '\"' . s:gsub(s:gsub(a:arg, '\"', '\"\"'), '\\%', '\"%\"') . '\"'\n  endif\nendfunction\n\nfunction! s:shellesc(arg) abort\n  if type(a:arg) == type([])\n    return join(map(copy(a:arg), 's:shellesc(v:val)'))\n  elseif a:arg =~# '^[A-Za-z0-9_/:.-]\\+$'\n    return a:arg\n  elseif s:winshell()\n    return '\"' . s:gsub(s:gsub(a:arg, '\"', '\"\"'), '\\%', '\"%\"') . '\"'\n  else\n    return shellescape(a:arg)\n  endif\nendfunction\n\nfunction! s:fnameescape(file) abort\n  if type(a:file) == type([])\n    return join(map(copy(a:file), 's:fnameescape(v:val)'))\n  else\n    return fnameescape(a:file)\n  endif\nendfunction\n\nfunction! fugitive#UrlDecode(str) abort\n  return substitute(a:str, '%\\(\\x\\x\\)', '\\=iconv(nr2char(\"0x\".submatch(1)), \"utf-8\", \"latin1\")', 'g')\nendfunction\n\nfunction! s:UrlEncode(str) abort\n  return substitute(a:str, '[%#?&;+=\\<> [:cntrl:]]', '\\=printf(\"%%%02X\", char2nr(submatch(0)))', 'g')\nendfunction\n\nfunction! s:PathUrlEncode(str) abort\n  return substitute(a:str, '[%#?[:cntrl:]]', '\\=printf(\"%%%02X\", char2nr(submatch(0)))', 'g')\nendfunction\n\nfunction! s:PathJoin(prefix, str) abort\n  if a:prefix =~# '://'\n    return a:prefix . s:PathUrlEncode(a:str)\n  else\n    return a:prefix . a:str\n  endif\nendfunction\n\nfunction! s:throw(string) abort\n  throw 'fugitive: '.a:string\nendfunction\n\nfunction! s:VersionCheck() abort\n  if v:version < 704\n    return 'return ' . string('echoerr \"fugitive: Vim 7.4 or newer required\"')\n  elseif empty(fugitive#GitVersion())\n    let exe = get(s:GitCmd(), 0, '')\n    if len(exe) && !executable(exe)\n      return 'return ' . string('echoerr \"fugitive: cannot find ' . string(exe) . ' in PATH\"')\n    endif\n    return 'return ' . string('echoerr \"fugitive: cannot execute Git\"')\n  elseif !fugitive#GitVersion(1, 8, 5)\n    return 'return ' . string('echoerr \"fugitive: Git 1.8.5 or newer required\"')\n  else\n    if exists('b:git_dir') && empty(b:git_dir)\n      unlet! b:git_dir\n    endif\n    return ''\n  endif\nendfunction\n\nlet s:worktree_error = \"core.worktree is required when using an external Git dir\"\nfunction! s:DirCheck(...) abort\n  let dir = call('FugitiveGitDir', a:000)\n  if !empty(dir) && FugitiveWorkTree(dir, 1) is# 0\n    return 'return ' . string('echoerr \"fugitive: ' . s:worktree_error . '\"')\n  elseif !empty(dir)\n    return ''\n  elseif empty(bufname(''))\n    return 'return ' . string('echoerr \"fugitive: working directory does not belong to a Git repository\"')\n  else\n    return 'return ' . string('echoerr \"fugitive: file does not belong to a Git repository\"')\n  endif\nendfunction\n\nfunction! s:Mods(mods, ...) abort\n  let mods = substitute(a:mods, '\\C<mods>', '', '')\n  let mods = mods =~# '\\S$' ? mods . ' ' : mods\n  if a:0 && mods !~# '\\<\\d*\\%(aboveleft\\|belowright\\|leftabove\\|rightbelow\\|topleft\\|botright\\|tab\\)\\>'\n    let default = a:1\n    if default ==# 'SpanOrigin'\n      if s:OriginBufnr() > 0 && (mods =~# '\\<vertical\\>' ? &winfixheight : &winfixwidth)\n        let default = 'Edge'\n      else\n        let default = ''\n      endif\n    endif\n    if default ==# 'Edge'\n      if mods =~# '\\<vertical\\>' ? &splitright : &splitbelow\n        let mods = 'botright ' . mods\n      else\n        let mods = 'topleft ' . mods\n      endif\n    else\n      let mods = default . ' ' . mods\n    endif\n  endif\n  return substitute(mods, '\\s\\+', ' ', 'g')\nendfunction\n\nif exists('+shellslash')\n\n  let s:dir_commit_file = '\\c^fugitive://\\%(/[^/]\\@=\\)\\=\\([^?#]\\{-1,\\}\\)//\\%(\\(\\x\\{40,\\}\\|[0-3]\\)\\(/[^?#]*\\)\\=\\)\\=$'\n\n  function! s:Slash(path) abort\n    return tr(a:path, '\\', '/')\n  endfunction\n\n  function! s:VimSlash(path) abort\n    return tr(a:path, '\\/', &shellslash ? '//' : '\\\\')\n  endfunction\n\nelse\n\n  let s:dir_commit_file = '\\c^fugitive://\\([^?#]\\{-\\}\\)//\\%(\\(\\x\\{40,\\}\\|[0-3]\\)\\(/[^?#]*\\)\\=\\)\\=$'\n\n  function! s:Slash(path) abort\n    return a:path\n  endfunction\n\n  function! s:VimSlash(path) abort\n    return a:path\n  endfunction\n\nendif\n\nfunction! s:AbsoluteVimPath(...) abort\n  if a:0 && type(a:1) == type('')\n    let path = a:1\n  else\n    let path = bufname(a:0 && a:1 > 0 ? a:1 : '')\n    if getbufvar(a:0 && a:1 > 0 ? a:1 : '', '&buftype') !~# '^\\%(nowrite\\|acwrite\\)\\=$'\n      return path\n    endif\n  endif\n  if s:Slash(path) =~# '^/\\|^\\a\\+:'\n    return path\n  else\n    return getcwd() . matchstr(getcwd(), '[\\\\/]') . path\n  endif\nendfunction\n\nfunction! s:Resolve(path) abort\n  let path = resolve(a:path)\n  if has('win32')\n    let path = s:VimSlash(fnamemodify(fnamemodify(path, ':h'), ':p') . fnamemodify(path, ':t'))\n  endif\n  return path\nendfunction\n\nfunction! s:FileIgnoreCase(for_completion) abort\n  return (exists('+fileignorecase') && &fileignorecase)\n        \\ || (a:for_completion && exists('+wildignorecase') && &wildignorecase)\nendfunction\n\nfunction! s:cpath(path, ...) abort\n  if s:FileIgnoreCase(0)\n    let path = s:VimSlash(tolower(a:path))\n  else\n    let path = s:VimSlash(a:path)\n  endif\n  return a:0 ? path ==# s:cpath(a:1) : path\nendfunction\n\nlet s:quote_chars = {\n      \\ \"\\007\": 'a', \"\\010\": 'b', \"\\011\": 't', \"\\012\": 'n', \"\\013\": 'v', \"\\014\": 'f', \"\\015\": 'r',\n      \\ '\"': '\"', '\\': '\\'}\n\nlet s:unquote_chars = {\n      \\ 'a': \"\\007\", 'b': \"\\010\", 't': \"\\011\", 'n': \"\\012\", 'v': \"\\013\", 'f': \"\\014\", 'r': \"\\015\",\n      \\ '\"': '\"', '\\': '\\'}\n\nfunction! s:Quote(string) abort\n  let string = substitute(a:string, \"[\\001-\\037\\\"\\\\\\177]\", '\\=\"\\\\\" . get(s:quote_chars, submatch(0), printf(\"%03o\", char2nr(submatch(0))))', 'g')\n  if string !=# a:string\n    return '\"' . string . '\"'\n  else\n    return string\n  endif\nendfunction\n\nfunction! fugitive#Unquote(string) abort\n  let string = substitute(a:string, \"\\t*$\", '', '')\n  if string =~# '^\".*\"$'\n    return substitute(string[1:-2], '\\\\\\(\\o\\o\\o\\|.\\)', '\\=get(s:unquote_chars, submatch(1), iconv(nr2char(\"0\" . submatch(1)), \"utf-8\", \"latin1\"))', 'g')\n  else\n    return string\n  endif\nendfunction\n\nlet s:executables = {}\n\nfunction! s:executable(binary) abort\n  if !has_key(s:executables, a:binary)\n    let s:executables[a:binary] = executable(a:binary)\n  endif\n  return s:executables[a:binary]\nendfunction\n\nif !exists('s:temp_scripts')\n  let s:temp_scripts = {}\nendif\nfunction! s:TempScript(...) abort\n  let body = join(a:000, \"\\n\")\n  if !has_key(s:temp_scripts, body)\n    let s:temp_scripts[body] = tempname() . '.sh'\n  endif\n  let temp = s:temp_scripts[body]\n  if !filereadable(temp)\n    call writefile(['#!/bin/sh'] + a:000, temp)\n  endif\n  let temp = FugitiveGitPath(temp)\n  if temp =~# '\\s'\n    let temp = '\"' . temp . '\"'\n  endif\n  return temp\nendfunction\n\nfunction! s:DoAutocmd(...) abort\n  return join(map(copy(a:000), \"'doautocmd <nomodeline>' . v:val\"), '|')\nendfunction\n\nfunction! s:Map(mode, lhs, rhs, ...) abort\n  let maps = []\n  let flags = a:0 && type(a:1) == type('') ? a:1 : ''\n  let defer = flags =~# '<unique>'\n  let flags = substitute(flags, '<unique>', '', '') . (a:rhs =~# '<Plug>' ? '' : '<script>') . '<nowait>'\n  for mode in split(a:mode, '\\zs')\n    if a:0 <= 1\n      call add(maps, mode.'map <buffer>' . substitute(flags, '<unique>', '', '') . ' <Plug>fugitive:' . a:lhs . ' ' . a:rhs)\n    endif\n    let skip = 0\n    let head = a:lhs\n    let tail = ''\n    let keys = get(g:, mode.'remap', {})\n    if type(keys) == type([])\n      continue\n    endif\n    while !empty(head)\n      if has_key(keys, head)\n        let head = keys[head]\n        let skip = empty(head)\n        break\n      endif\n      let tail = matchstr(head, '<[^<>]*>$\\|.$') . tail\n      let head = substitute(head, '<[^<>]*>$\\|.$', '', '')\n    endwhile\n    if !skip && (!defer || empty(mapcheck(head.tail, mode)))\n      call add(maps, mode.'map <buffer>' . flags . ' ' . head.tail . ' ' . a:rhs)\n      if a:0 > 1 && a:2\n        let b:undo_ftplugin = get(b:, 'undo_ftplugin', 'exe') .\n              \\ '|sil! exe \"' . mode . 'unmap <buffer> ' . head.tail . '\"'\n      endif\n    endif\n  endfor\n  exe join(maps, '|')\n  return ''\nendfunction\n\nfunction! fugitive#Autowrite() abort\n  if &autowrite || &autowriteall\n    try\n      if &confirm\n        let reconfirm = 1\n        setglobal noconfirm\n      endif\n      silent! wall\n    finally\n      if exists('reconfirm')\n        setglobal confirm\n      endif\n    endtry\n  endif\n  return ''\nendfunction\n\nfunction! fugitive#Wait(job_or_jobs, ...) abort\n  let original = type(a:job_or_jobs) == type([]) ? copy(a:job_or_jobs) : [a:job_or_jobs]\n  let jobs = map(copy(original), 'type(v:val) ==# type({}) ? get(v:val, \"job\", \"\") : v:val')\n  call filter(jobs, 'type(v:val) !=# type(\"\")')\n  let timeout_ms = a:0 ? a:1 : -1\n  if exists('*jobwait')\n    call map(copy(jobs), 'chanclose(v:val, \"stdin\")')\n    call jobwait(jobs, timeout_ms)\n    let jobs = map(copy(original), 'type(v:val) ==# type({}) ? get(v:val, \"job\", \"\") : v:val')\n    call filter(jobs, 'type(v:val) !=# type(\"\")')\n    if len(jobs)\n      sleep 1m\n    endif\n  else\n    for job in jobs\n      if ch_status(job) ==# 'open'\n        call ch_close_in(job)\n      endif\n    endfor\n    let i = 0\n    for job in jobs\n      while ch_status(job) !~# '^closed$\\|^fail$' || job_status(job) ==# 'run'\n        if i == timeout_ms\n          break\n        endif\n        let i += 1\n        sleep 1m\n      endwhile\n    endfor\n  endif\n  return a:job_or_jobs\nendfunction\n\nfunction! s:JobVimExit(dict, callback, temp, job, status) abort\n  let a:dict.exit_status = a:status\n  let a:dict.stderr = readfile(a:temp . '.err', 'b')\n  call delete(a:temp . '.err')\n  let a:dict.stdout = readfile(a:temp . '.out', 'b')\n  call delete(a:temp . '.out')\n  call delete(a:temp . '.in')\n  call remove(a:dict, 'job')\n  call call(a:callback[0], [a:dict] + a:callback[1:-1])\nendfunction\n\nfunction! s:JobNvimExit(dict, callback, job, data, type) dict abort\n  let a:dict.stdout = self.stdout\n  let a:dict.stderr = self.stderr\n  let a:dict.exit_status = a:data\n  call remove(a:dict, 'job')\n  call call(a:callback[0], [a:dict] + a:callback[1:-1])\nendfunction\n\nfunction! s:JobExecute(argv, jopts, stdin, callback, ...) abort\n  let dict = a:0 ? a:1 : {}\n  let cb = len(a:callback) ? a:callback : [function('len')]\n  if exists('*jobstart')\n    call extend(a:jopts, {\n          \\ 'stdout_buffered': v:true,\n          \\ 'stderr_buffered': v:true,\n          \\ 'on_exit': function('s:JobNvimExit', [dict, cb])})\n    try\n      let dict.job = jobstart(a:argv, a:jopts)\n      if !empty(a:stdin)\n        call chansend(dict.job, a:stdin)\n      endif\n      call chanclose(dict.job, 'stdin')\n    catch /^Vim\\%((\\a\\+)\\)\\=:E475:/\n      let [dict.exit_status, dict.stdout, dict.stderr] = [122, [''], ['']]\n    endtry\n  elseif exists('*ch_close_in')\n    let temp = tempname()\n    call extend(a:jopts, {\n          \\ 'out_io': 'file',\n          \\ 'out_name': temp . '.out',\n          \\ 'err_io': 'file',\n          \\ 'err_name': temp . '.err',\n          \\ 'exit_cb': function('s:JobVimExit', [dict, cb, temp])})\n    if a:stdin ==# ['']\n      let a:jopts.in_io = 'null'\n    elseif !empty(a:stdin)\n      let a:jopts.in_io = 'file'\n      let a:jopts.in_name = temp . '.in'\n      call writefile(a:stdin, a:jopts.in_name, 'b')\n    endif\n    let dict.job = job_start(a:argv, a:jopts)\n    if job_status(dict.job) ==# 'fail'\n      let [dict.exit_status, dict.stdout, dict.stderr] = [122, [''], ['']]\n      unlet dict.job\n    endif\n  elseif &shell !~# 'sh' || &shell =~# 'fish\\|\\%(powershell\\|pwsh\\)\\%(\\.exe\\)\\=$'\n    throw 'fugitive: Vim 8 or higher required to use ' . &shell\n  else\n    let cmd = s:shellesc(a:argv)\n    let outfile = tempname()\n    try\n      if len(a:stdin)\n        call writefile(a:stdin, outfile . '.in', 'b')\n        let cmd = ' (' . cmd . ' >' . outfile . ' <' . outfile . '.in) '\n      else\n        let cmd = ' (' . cmd . ' >' . outfile . ') '\n      endif\n      let dict.stderr = split(system(cmd), \"\\n\", 1)\n      let dict.exit_status = v:shell_error\n      let dict.stdout = readfile(outfile, 'b')\n      call call(cb[0], [dict] + cb[1:-1])\n    finally\n      call delete(outfile)\n      call delete(outfile . '.in')\n    endtry\n  endif\n  if empty(a:callback)\n    call fugitive#Wait(dict)\n  endif\n  return dict\nendfunction\n\nfunction! s:add_methods(namespace, method_names) abort\n  for name in a:method_names\n    let s:{a:namespace}_prototype[name] = s:function('s:'.a:namespace.'_'.name)\n  endfor\nendfunction\n\n\" Section: Git\n\nlet s:run_jobs = (exists('*ch_close_in') || exists('*jobstart')) && exists('*bufwinid')\n\nfunction! s:GitCmd() abort\n  if !exists('g:fugitive_git_executable')\n    return ['git']\n  elseif type(g:fugitive_git_executable) == type([])\n    return g:fugitive_git_executable\n  else\n    let dquote = '\"\\%([^\"]\\|\"\"\\|\\\\\"\\)*\"\\|'\n    let string = g:fugitive_git_executable\n    let list = []\n    if string =~# '^\\w\\+='\n      call add(list, '/usr/bin/env')\n    endif\n    while string =~# '\\S'\n      let arg = matchstr(string, '^\\s*\\%(' . dquote . '''[^'']*''\\|\\\\.\\|[^' . \"\\t\" . ' |]\\)\\+')\n      let string = strpart(string, len(arg))\n      let arg = substitute(arg, '^\\s\\+', '', '')\n      let arg = substitute(arg,\n            \\ '\\(' . dquote . '''\\%(''''\\|[^'']\\)*''\\|\\\\[' . s:fnameescape . ']\\|^\\\\[>+-]\\|' . s:commit_expand . '\\)\\|' . s:expand,\n            \\ '\\=submatch(0)[0] ==# \"\\\\\" ? submatch(0)[1] : submatch(0)[1:-2]', 'g')\n      call add(list, arg)\n    endwhile\n    return list\n  endif\nendfunction\n\nfunction! s:GitShellCmd() abort\n  if !exists('g:fugitive_git_executable')\n    return 'git'\n  elseif type(g:fugitive_git_executable) == type([])\n    return s:shellesc(g:fugitive_git_executable)\n  else\n    return g:fugitive_git_executable\n  endif\nendfunction\n\nfunction! s:UserCommandCwd(dir) abort\n  let tree = s:Tree(a:dir)\n  return len(tree) ? s:VimSlash(tree) : getcwd()\nendfunction\n\nfunction! s:UserCommandList(...) abort\n  if !fugitive#GitVersion(1, 8, 5)\n    throw 'fugitive: Git 1.8.5 or higher required'\n  endif\n  if !exists('g:fugitive_git_command')\n    let git = s:GitCmd()\n  elseif type(g:fugitive_git_command) == type([])\n    let git = g:fugitive_git_command\n  else\n    let git = split(g:fugitive_git_command, '\\s\\+')\n  endif\n  let flags = []\n  if a:0 && type(a:1) == type({})\n    let git = copy(get(a:1, 'git', git))\n    let flags = get(a:1, 'flags', flags)\n    let dir = a:1.git_dir\n  elseif a:0\n    let dir = s:GitDir(a:1)\n  else\n    let dir = ''\n  endif\n  if len(dir)\n    let tree = s:Tree(dir)\n    if empty(tree)\n      call add(git, '--git-dir=' . FugitiveGitPath(dir))\n    else\n      if !s:cpath(tree . '/.git', dir) || len($GIT_DIR)\n        call add(git, '--git-dir=' . FugitiveGitPath(dir))\n      endif\n      if !s:cpath(tree, getcwd())\n        call extend(git, ['-C', FugitiveGitPath(tree)])\n      endif\n    endif\n  endif\n  return git + flags\nendfunction\n\nlet s:git_versions = {}\nfunction! fugitive#GitVersion(...) abort\n  let git = s:GitShellCmd()\n  if !has_key(s:git_versions, git)\n    let s:git_versions[git] = matchstr(get(s:JobExecute(s:GitCmd() + ['--version'], {}, [], [], {}).stdout, 0, ''), '\\d[^[:space:]]\\+')\n  endif\n  if !a:0\n    return s:git_versions[git]\n  endif\n  let components = split(s:git_versions[git], '\\D\\+')\n  if empty(components)\n    return -1\n  endif\n  for i in range(len(a:000))\n    if a:000[i] > +get(components, i)\n      return 0\n    elseif a:000[i] < +get(components, i)\n      return 1\n    endif\n  endfor\n  return a:000[i] ==# get(components, i)\nendfunction\n\nfunction! s:Dir(...) abort\n  return a:0 ? FugitiveGitDir(a:1) : FugitiveGitDir()\nendfunction\n\nfunction! s:GitDir(...) abort\n  return a:0 ? FugitiveGitDir(a:1) : FugitiveGitDir()\nendfunction\n\nfunction! s:InitializeBuffer(repo) abort\n  let b:git_dir = s:GitDir(a:repo)\nendfunction\n\nfunction! s:SameRepo(one, two) abort\n  let one = s:GitDir(a:one)\n  return !empty(one) && one ==# s:GitDir(a:two)\nendfunction\n\nif exists('+shellslash')\n  function! s:DirUrlPrefix(dir) abort\n    let gd = s:GitDir(a:dir)\n    return 'fugitive://' . (gd =~# '^[^/]' ? '/' : '') . s:PathUrlEncode(gd) . '//'\n  endfunction\nelse\n  function! s:DirUrlPrefix(dir) abort\n    return 'fugitive://' . s:PathUrlEncode(s:GitDir(a:dir)) . '//'\n  endfunction\nendif\n\nfunction! s:Tree(...) abort\n  return a:0 ? FugitiveWorkTree(a:1) : FugitiveWorkTree()\nendfunction\n\nfunction! s:HasOpt(args, ...) abort\n  let args = a:args[0 : index(a:args, '--')]\n  let opts = copy(a:000)\n  if type(opts[0]) == type([])\n    if empty(args) || index(opts[0], args[0]) == -1\n      return 0\n    endif\n    call remove(opts, 0)\n  endif\n  for opt in opts\n    if index(args, opt) != -1\n      return 1\n    endif\n  endfor\nendfunction\n\nfunction! s:PreparePathArgs(cmd, dir, literal, explicit) abort\n  if !a:explicit\n    call insert(a:cmd, '--literal-pathspecs')\n  endif\n  let split = index(a:cmd, '--')\n  for i in range(split < 0 ? len(a:cmd) : split)\n      if type(a:cmd[i]) == type(0)\n        if a:literal\n          let a:cmd[i] = fugitive#Path(bufname(a:cmd[i]), './', a:dir)\n        else\n          let a:cmd[i] = fugitive#Path(bufname(a:cmd[i]), ':(top,literal)', a:dir)\n        endif\n      endif\n  endfor\n  if split < 0\n    return a:cmd\n  endif\n  for i in range(split + 1, len(a:cmd) - 1)\n    if type(a:cmd[i]) == type(0)\n      if a:literal\n        let a:cmd[i] = fugitive#Path(bufname(a:cmd[i]), './', a:dir)\n      else\n        let a:cmd[i] = fugitive#Path(bufname(a:cmd[i]), ':(top,literal)', a:dir)\n      endif\n    elseif !a:explicit\n      let a:cmd[i] = fugitive#Path(a:cmd[i], './', a:dir)\n    endif\n  endfor\n  return a:cmd\nendfunction\n\nlet s:git_index_file_env = {}\nfunction! s:GitIndexFileEnv() abort\n  if $GIT_INDEX_FILE =~# '^/\\|^\\a:' && !has_key(s:git_index_file_env, $GIT_INDEX_FILE)\n    let s:git_index_file_env[$GIT_INDEX_FILE] = s:Slash(FugitiveVimPath($GIT_INDEX_FILE))\n  endif\n  return get(s:git_index_file_env, $GIT_INDEX_FILE, '')\nendfunction\n\nfunction! s:PrepareEnv(env, dir) abort\n  if len($GIT_INDEX_FILE) && len(s:Tree(a:dir)) && !has_key(a:env, 'GIT_INDEX_FILE')\n    let index_dir = substitute(s:GitIndexFileEnv(), '[^/]\\+$', '', '')\n    let our_dir = fugitive#Find('.git/', a:dir)\n    if !s:cpath(index_dir, our_dir) && !s:cpath(resolve(index_dir), our_dir)\n      let a:env['GIT_INDEX_FILE'] = FugitiveGitPath(fugitive#Find('.git/index', a:dir))\n    endif\n  endif\n  if len($GIT_WORK_TREE)\n    let a:env['GIT_WORK_TREE'] = '.'\n  endif\nendfunction\n\nlet s:prepare_env = {\n      \\ 'sequence.editor': 'GIT_SEQUENCE_EDITOR',\n      \\ 'core.editor': 'GIT_EDITOR',\n      \\ 'core.askpass': 'GIT_ASKPASS',\n      \\ }\nfunction! fugitive#PrepareDirEnvGitFlagsArgs(...) abort\n  if !fugitive#GitVersion(1, 8, 5)\n    throw 'fugitive: Git 1.8.5 or higher required'\n  endif\n  let git = s:GitCmd()\n  if a:0 == 1 && type(a:1) == type({}) && (has_key(a:1, 'fugitive_dir') || has_key(a:1, 'git_dir')) && has_key(a:1, 'flags') && has_key(a:1, 'args')\n    let cmd = a:1.flags + a:1.args\n    let dir = s:Dir(a:1)\n    if has_key(a:1, 'git')\n      let git = a:1.git\n    endif\n    let env = get(a:1, 'env', {})\n  else\n    let list_args = []\n    let cmd = []\n    for l:.arg in a:000\n      if type(arg) ==# type([])\n        call extend(list_args, arg)\n      else\n        call add(cmd, arg)\n      endif\n    endfor\n    call extend(cmd, list_args)\n    let env = {}\n  endif\n  let autoenv = {}\n  let explicit_pathspec_option = 0\n  let literal_pathspecs = 1\n  let i = 0\n  let arg_count = 0\n  while i < len(cmd)\n    if type(cmd[i]) == type({})\n      if has_key(cmd[i], 'fugitive_dir') || has_key(cmd[i], 'git_dir')\n        let dir = s:Dir(cmd[i])\n      endif\n      if has_key(cmd[i], 'git')\n        let git = cmd[i].git\n      endif\n      if has_key(cmd[i], 'env')\n        call extend(env, cmd[i].env)\n      endif\n      call remove(cmd, i)\n    elseif cmd[i] =~# '^$\\|[\\/.]' && cmd[i] !~# '^-'\n      let dir = s:Dir(remove(cmd, i))\n    elseif cmd[i] =~# '^--git-dir='\n      let dir = s:Dir(remove(cmd, i)[10:-1])\n    elseif type(cmd[i]) ==# type(0)\n      let dir = s:Dir(remove(cmd, i))\n    elseif cmd[i] ==# '-c' && len(cmd) > i + 1\n      let key = matchstr(cmd[i+1], '^[^=]*')\n      if has_key(s:prepare_env, tolower(key))\n        let var = s:prepare_env[tolower(key)]\n        let val = matchstr(cmd[i+1], '=\\zs.*')\n        let autoenv[var] = val\n      endif\n      let i += 2\n    elseif cmd[i] =~# '^--.*pathspecs$'\n      let literal_pathspecs = (cmd[i] ==# '--literal-pathspecs')\n      let explicit_pathspec_option = 1\n      let i += 1\n    elseif cmd[i] !~# '^-'\n      let arg_count = len(cmd) - i\n      break\n    else\n      let i += 1\n    endif\n  endwhile\n  if !exists('dir')\n    let dir = s:Dir()\n  endif\n  call extend(autoenv, env)\n  call s:PrepareEnv(autoenv, dir)\n  if len($GPG_TTY) && !has_key(autoenv, 'GPG_TTY')\n    let autoenv.GPG_TTY = ''\n  endif\n  call s:PreparePathArgs(cmd, dir, literal_pathspecs, explicit_pathspec_option)\n  return [dir, env, extend(autoenv, env), git, cmd[0 : -arg_count-1], arg_count ? cmd[-arg_count : -1] : []]\nendfunction\n\nfunction! s:BuildEnvPrefix(env) abort\n  let pre = ''\n  let env = items(a:env)\n  if empty(env)\n    return ''\n  elseif &shell =~# '\\%(powershell\\|pwsh\\)\\%(\\.exe\\)\\=$'\n    return join(map(env, '\"$Env:\" . v:val[0] . \" = ''\" . substitute(v:val[1], \"''\", \"''''\", \"g\") . \"''; \"'), '')\n  elseif s:winshell()\n    return join(map(env, '\"set \" . substitute(join(v:val, \"=\"), \"[&|<>^]\", \"^^^&\", \"g\") . \"& \"'), '')\n  else\n    return '/usr/bin/env ' . s:shellesc(map(env, 'join(v:val, \"=\")')) . ' '\n  endif\nendfunction\n\nfunction! s:JobOpts(cmd, env) abort\n  if empty(a:env)\n    return [a:cmd, {}]\n  elseif has('patch-8.2.0239') ||\n        \\ has('nvim') && api_info().version.api_level - api_info().version.api_prerelease >= 7 ||\n        \\ has('patch-8.0.0902') && !has('nvim') && (!has('win32') || empty(filter(keys(a:env), 'exists(\"$\" . v:val)')))\n    return [a:cmd, {'env': a:env}]\n  endif\n  let envlist = map(items(a:env), 'join(v:val, \"=\")')\n  if !has('win32')\n    return [['/usr/bin/env'] + envlist + a:cmd, {}]\n  else\n    let pre = join(map(envlist, '\"set \" . substitute(v:val, \"[&|<>^]\", \"^^^&\", \"g\") . \"& \"'), '')\n    if len(a:cmd) == 3 && a:cmd[0] ==# 'cmd.exe' && a:cmd[1] ==# '/c'\n      return [a:cmd[0:1] + [pre . a:cmd[2]], {}]\n    else\n      return [['cmd.exe', '/c', pre . s:WinShellEsc(a:cmd)], {}]\n    endif\n  endif\nendfunction\n\nfunction! s:PrepareJob(opts) abort\n  let dict = {'argv': a:opts.argv}\n  if has_key(a:opts, 'env')\n    let dict.env = a:opts.env\n  endif\n  let [argv, jopts] = s:JobOpts(a:opts.argv, get(a:opts, 'env', {}))\n  if has_key(a:opts, 'cwd')\n    if has('patch-8.0.0902')\n      let jopts.cwd = a:opts.cwd\n      let dict.cwd = a:opts.cwd\n    else\n      throw 'fugitive: cwd unsupported'\n    endif\n  endif\n  return [argv, jopts, dict]\nendfunction\n\nfunction! fugitive#PrepareJob(...) abort\n  if a:0 == 1 && type(a:1) == type({}) && has_key(a:1, 'argv') && !has_key(a:1, 'args')\n    return s:PrepareJob(a:1)\n  endif\n  let [repo, user_env, exec_env, git, flags, args] = call('fugitive#PrepareDirEnvGitFlagsArgs', a:000)\n  let dir = s:GitDir(repo)\n  let dict = {'git': git, 'git_dir': dir, 'flags': flags, 'args': args}\n  if len(user_env)\n    let dict.env = user_env\n  endif\n  let cmd = flags + args\n  let tree = s:Tree(repo)\n  if empty(tree) || index(cmd, '--') == len(cmd) - 1\n    let dict.cwd = getcwd()\n    call extend(cmd, ['--git-dir=' . FugitiveGitPath(dir)], 'keep')\n  else\n    let dict.cwd = s:VimSlash(tree)\n    call extend(cmd, ['-C', FugitiveGitPath(tree)], 'keep')\n    if !s:cpath(tree . '/.git', dir) || len($GIT_DIR)\n      call extend(cmd, ['--git-dir=' . FugitiveGitPath(dir)], 'keep')\n    endif\n  endif\n  call extend(cmd, git, 'keep')\n  return s:JobOpts(cmd, exec_env) + [dict]\nendfunction\n\nfunction! fugitive#Execute(...) abort\n  let cb = copy(a:000)\n  let cmd = []\n  let stdin = []\n  while len(cb) && type(cb[0]) !=# type(function('tr'))\n    if type(cb[0]) ==# type({}) && has_key(cb[0], 'stdin')\n      if type(cb[0].stdin) == type([])\n        call extend(stdin, cb[0].stdin)\n      elseif type(cb[0].stdin) == type('')\n        call extend(stdin, readfile(cb[0].stdin, 'b'))\n      endif\n      if len(keys(cb[0])) == 1\n        call remove(cb, 0)\n        continue\n      endif\n    endif\n    call add(cmd, remove(cb, 0))\n  endwhile\n  let [argv, jopts, dict] = call('fugitive#PrepareJob', cmd)\n  return s:JobExecute(argv, jopts, stdin, cb, dict)\nendfunction\n\nfunction! s:BuildShell(dir, env, git, args) abort\n  let cmd = copy(a:args)\n  let tree = s:Tree(a:dir)\n  let pre = s:BuildEnvPrefix(a:env)\n  if empty(tree) || index(cmd, '--') == len(cmd) - 1\n    call insert(cmd, '--git-dir=' . FugitiveGitPath(a:dir))\n  else\n    call extend(cmd, ['-C', FugitiveGitPath(tree)], 'keep')\n    if !s:cpath(tree . '/.git', a:dir) || len($GIT_DIR)\n      call extend(cmd, ['--git-dir=' . FugitiveGitPath(a:dir)], 'keep')\n    endif\n  endif\n  return pre . join(map(a:git + cmd, 's:shellesc(v:val)'))\nendfunction\n\nfunction! s:JobNvimCallback(lines, job, data, type) abort\n  let a:lines[-1] .= remove(a:data, 0)\n  call extend(a:lines, a:data)\nendfunction\n\nfunction! s:SystemList(cmd) abort\n  let exit = []\n  if exists('*jobstart')\n    let lines = ['']\n    let jopts = {\n          \\ 'on_stdout': function('s:JobNvimCallback', [lines]),\n          \\ 'on_stderr': function('s:JobNvimCallback', [lines]),\n          \\ 'on_exit': { j, code, _ -> add(exit, code) }}\n    let job = jobstart(a:cmd, jopts)\n    call chanclose(job, 'stdin')\n    call jobwait([job])\n    if empty(lines[-1])\n      call remove(lines, -1)\n    endif\n    return [lines, exit[0]]\n  elseif exists('*ch_close_in')\n    let lines = []\n    let jopts = {\n          \\ 'out_cb': { j, str -> add(lines, str) },\n          \\ 'err_cb': { j, str -> add(lines, str) },\n          \\ 'exit_cb': { j, code -> add(exit, code) }}\n    let job = job_start(a:cmd, jopts)\n    call ch_close_in(job)\n    while ch_status(job) !~# '^closed$\\|^fail$' || job_status(job) ==# 'run'\n      sleep 1m\n    endwhile\n    return [lines, exit[0]]\n  else\n    let [output, exec_error] = s:SystemError(s:shellesc(a:cmd))\n    let lines = split(output, \"\\n\", 1)\n    if empty(lines[-1])\n      call remove(lines, -1)\n    endif\n    return [lines, v:shell_error]\n  endif\nendfunction\n\nfunction! fugitive#ShellCommand(...) abort\n  let [repo, _, env, git, flags, args] = call('fugitive#PrepareDirEnvGitFlagsArgs', a:000)\n  return s:BuildShell(s:GitDir(repo), env, git, flags + args)\nendfunction\n\nfunction! s:SystemError(cmd, ...) abort\n  let cmd = type(a:cmd) == type([]) ? s:shellesc(a:cmd) : a:cmd\n  try\n    if &shellredir ==# '>' && &shell =~# 'sh\\|cmd'\n      let shellredir = &shellredir\n      if &shell =~# 'csh'\n        set shellredir=>&\n      else\n        set shellredir=>%s\\ 2>&1\n      endif\n    endif\n    if exists('+guioptions') && &guioptions =~# '!'\n      let guioptions = &guioptions\n      set guioptions-=!\n    endif\n    let out = call('system', [cmd] + a:000)\n    return [out, v:shell_error]\n  catch /^Vim\\%((\\a\\+)\\)\\=:E484:/\n    let opts = ['shell', 'shellcmdflag', 'shellredir', 'shellquote', 'shellxquote', 'shellxescape', 'shellslash']\n    call filter(opts, 'exists(\"+\".v:val) && !empty(eval(\"&\".v:val))')\n    call map(opts, 'v:val.\"=\".eval(\"&\".v:val)')\n    call s:throw('failed to run `' . cmd . '` with ' . join(opts, ' '))\n  finally\n    if exists('shellredir')\n      let &shellredir = shellredir\n    endif\n    if exists('guioptions')\n      let &guioptions = guioptions\n    endif\n  endtry\nendfunction\n\nfunction! s:ChompStderr(...) abort\n  let r = call('fugitive#Execute', a:000)\n  return !r.exit_status ? '' : len(r.stderr) > 1 ? s:JoinChomp(r.stderr) : 'unknown Git error' . string(r)\nendfunction\n\nfunction! s:ChompDefault(default, ...) abort\n  let r = call('fugitive#Execute', a:000)\n  return r.exit_status ? a:default : s:JoinChomp(r.stdout)\nendfunction\n\nfunction! s:LinesError(...) abort\n  let r = call('fugitive#Execute', a:000)\n  if empty(r.stdout[-1])\n    call remove(r.stdout, -1)\n  endif\n  return [r.exit_status ? [] : r.stdout, r.exit_status]\nendfunction\n\nfunction! s:TreeChomp(...) abort\n  let r = call('fugitive#Execute', a:000)\n  if !r.exit_status\n    return s:JoinChomp(r.stdout)\n  endif\n  throw 'fugitive: error running `' . call('fugitive#ShellCommand', a:000) . '`: ' . s:JoinChomp(r.stderr)\nendfunction\n\nfunction! s:StdoutToFile(out, cmd, ...) abort\n  let [argv, jopts, _] = fugitive#PrepareJob(a:cmd)\n  let exit = []\n  if exists('*jobstart')\n    call extend(jopts, {\n          \\ 'stdout_buffered': v:true,\n          \\ 'stderr_buffered': v:true,\n          \\ 'on_exit': { j, code, _ -> add(exit, code) }})\n    let job = jobstart(argv, jopts)\n    if a:0\n      call chansend(job, a:1)\n    endif\n    call chanclose(job, 'stdin')\n    call jobwait([job])\n    if len(a:out)\n      call writefile(jopts.stdout, a:out, 'b')\n    endif\n    return [join(jopts.stderr, \"\\n\"), exit[0]]\n  elseif exists('*ch_close_in')\n    try\n      let err = tempname()\n      call extend(jopts, {\n            \\ 'out_io': len(a:out) ? 'file' : 'null',\n            \\ 'out_name': a:out,\n            \\ 'err_io': 'file',\n            \\ 'err_name': err,\n            \\ 'exit_cb': { j, code -> add(exit, code) }})\n      let job = job_start(argv, jopts)\n      if a:0\n        call ch_sendraw(job, a:1)\n      endif\n      call ch_close_in(job)\n      while ch_status(job) !~# '^closed$\\|^fail$' || job_status(job) ==# 'run'\n        sleep 1m\n      endwhile\n      return [join(readfile(err, 'b'), \"\\n\"), exit[0]]\n    finally\n      call delete(err)\n    endtry\n  elseif s:winshell() || &shell !~# 'sh' || &shell =~# 'fish\\|\\%(powershell\\|pwsh\\)\\%(\\.exe\\)\\=$'\n    throw 'fugitive: Vim 8 or higher required to use ' . &shell\n  else\n    let cmd = fugitive#ShellCommand(a:cmd)\n    return call('s:SystemError', [' (' . cmd . ' >' . (len(a:out) ? a:out : '/dev/null') . ') '] + a:000)\n  endif\nendfunction\n\nlet s:head_cache = {}\n\nfunction! fugitive#Head(...) abort\n  let dir = a:0 > 1 ? a:2 : s:Dir()\n  if empty(dir)\n    return ''\n  endif\n  let file = FugitiveActualDir(dir) . '/HEAD'\n  let ftime = getftime(file)\n  if ftime == -1\n    return ''\n  elseif ftime != get(s:head_cache, file, [-1])[0]\n    let s:head_cache[file] = [ftime, readfile(file)[0]]\n  endif\n  let head = s:head_cache[file][1]\n  let len = a:0 ? a:1 : 0\n  if head =~# '^ref: '\n    if len < 0\n      return strpart(head, 5)\n    else\n      return substitute(head, '\\C^ref: \\%(refs/\\%(heads/\\|remotes/\\|tags/\\)\\=\\)\\=', '', '')\n    endif\n  elseif head =~# '^\\x\\{40,\\}$'\n    return len < 0 ? head : strpart(head, 0, len)\n  else\n    return ''\n  endif\nendfunction\n\nfunction! fugitive#RevParse(rev, ...) abort\n  let hash = s:ChompDefault('', [a:0 ? a:1 : s:Dir(), 'rev-parse', '--verify', a:rev, '--'])\n  if hash =~# '^\\x\\{40,\\}$'\n    return hash\n  endif\n  throw 'fugitive: failed to parse revision ' . a:rev\nendfunction\n\n\" Section: Git config\n\nfunction! s:ConfigTimestamps(dir, dict) abort\n  let files = ['/etc/gitconfig', '~/.gitconfig',\n        \\ len($XDG_CONFIG_HOME) ? $XDG_CONFIG_HOME . '/git/config' : '~/.config/git/config']\n  if len(a:dir)\n    call add(files, fugitive#Find('.git/config', a:dir))\n  endif\n  call extend(files, get(a:dict, 'include.path', []))\n  return join(map(files, 'getftime(expand(v:val))'), ',')\nendfunction\n\nfunction! s:ConfigCallback(r, into) abort\n  let dict = a:into[1]\n  if has_key(dict, 'job')\n    call remove(dict, 'job')\n  endif\n  let lines = a:r.exit_status ? [] : split(tr(join(a:r.stdout, \"\\1\"), \"\\1\\n\", \"\\n\\1\"), \"\\1\", 1)[0:-2]\n  for line in lines\n    let key = matchstr(line, \"^[^\\n]*\")\n    if !has_key(dict, key)\n      let dict[key] = []\n    endif\n    if len(key) ==# len(line)\n      call add(dict[key], 1)\n    else\n      call add(dict[key], strpart(line, len(key) + 1))\n    endif\n  endfor\n  let callbacks = remove(dict, 'callbacks')\n  lockvar! dict\n  let a:into[0] = s:ConfigTimestamps(dict.git_dir, dict)\n  for callback in callbacks\n    call call(callback[0], [dict] + callback[1:-1])\n  endfor\nendfunction\n\nlet s:config_prototype = {}\n\nlet s:config = {}\nfunction! fugitive#ExpireConfig(...) abort\n  if !a:0 || a:1 is# 0\n    let s:config = {}\n  else\n    let key = a:1 is# '' ? '_' : s:GitDir(a:0 ? a:1 : -1)\n    if len(key) && has_key(s:config, key)\n      call remove(s:config, key)\n    endif\n  endif\nendfunction\n\nfunction! fugitive#Config(...) abort\n  let name = ''\n  let default = get(a:, 3, '')\n  if a:0 && type(a:1) == type(function('tr'))\n    let dir = s:Dir()\n    let callback = a:000\n  elseif a:0 > 1 && type(a:2) == type(function('tr'))\n    if type(a:1) == type({}) && has_key(a:1, 'GetAll')\n      if has_key(a:1, 'callbacks')\n        call add(a:1.callbacks, a:000[1:-1])\n      else\n        call call(a:2, [a:1] + a:000[2:-1])\n      endif\n      return a:1\n    else\n      let dir = s:Dir(a:1)\n      let callback = a:000[1:-1]\n    endif\n  elseif a:0 >= 2 && type(a:2) == type({}) && has_key(a:2, 'GetAll')\n    return get(fugitive#ConfigGetAll(a:1, a:2), -1, default)\n  elseif a:0 >= 2\n    let dir = s:Dir(a:2)\n    let name = a:1\n  elseif a:0 == 1 && type(a:1) == type({}) && has_key(a:1, 'GetAll')\n    return a:1\n  elseif a:0 == 1 && type(a:1) == type('') && a:1 =~# '^[[:alnum:]-]\\+\\.'\n    let dir = s:Dir()\n    let name = a:1\n  elseif a:0 == 1\n    let dir = s:Dir(a:1)\n  else\n    let dir = s:Dir()\n  endif\n  let name = substitute(name, '^[^.]\\+\\|[^.]\\+$', '\\L&', 'g')\n  let git_dir = s:GitDir(dir)\n  let dir_key = len(git_dir) ? git_dir : '_'\n  let [ts, dict] = get(s:config, dir_key, ['new', {}])\n  if !has_key(dict, 'job') && ts !=# s:ConfigTimestamps(git_dir, dict)\n    let dict = copy(s:config_prototype)\n    let dict.git_dir = git_dir\n    let into = ['running', dict]\n    let dict.callbacks = []\n    let exec = fugitive#Execute([dir, 'config', '--list', '-z', '--'], function('s:ConfigCallback'), into)\n    if has_key(exec, 'job')\n      let dict.job = exec.job\n    endif\n    let s:config[dir_key] = into\n  endif\n  if !exists('l:callback')\n    call fugitive#Wait(dict)\n  elseif has_key(dict, 'callbacks')\n    call add(dict.callbacks, callback)\n  else\n    call call(callback[0], [dict] + callback[1:-1])\n  endif\n  return len(name) ? get(fugitive#ConfigGetAll(name, dict), 0, default) : dict\nendfunction\n\nfunction! fugitive#ConfigGetAll(name, ...) abort\n  if a:0 && (type(a:name) !=# type('') || a:name !~# '^[[:alnum:]-]\\+\\.' && type(a:1) ==# type('') && a:1 =~# '^[[:alnum:]-]\\+\\.')\n    let config = fugitive#Config(a:name)\n    let name = a:1\n  else\n    let config = fugitive#Config(a:0 ? a:1 : s:Dir())\n    let name = a:name\n  endif\n  let name = substitute(name, '^[^.]\\+\\|[^.]\\+$', '\\L&', 'g')\n  call fugitive#Wait(config)\n  return name =~# '\\.' ? copy(get(config, name, [])) : []\nendfunction\n\nfunction! fugitive#ConfigGetRegexp(pattern, ...) abort\n  if type(a:pattern) !=# type('')\n    let config = fugitive#Config(a:name)\n    let pattern = a:0 ? a:1 : '.*'\n  else\n    let config = fugitive#Config(a:0 ? a:1 : s:Dir())\n    let pattern = a:pattern\n  endif\n  call fugitive#Wait(config)\n  let filtered = map(filter(copy(config), 'v:key =~# \"\\\\.\" && v:key =~# pattern'), 'copy(v:val)')\n  if pattern !~# '\\\\\\@<!\\%(\\\\\\\\\\)*\\\\z[se]'\n    return filtered\n  endif\n  let transformed = {}\n  for [k, v] in items(filtered)\n    let k = matchstr(k, pattern)\n    if len(k)\n      let transformed[k] = v\n    endif\n  endfor\n  return transformed\nendfunction\n\nfunction! s:config_GetAll(name) dict abort\n  let name = substitute(a:name, '^[^.]\\+\\|[^.]\\+$', '\\L&', 'g')\n  call fugitive#Wait(self)\n  return name =~# '\\.' ? copy(get(self, name, [])) : []\nendfunction\n\nfunction! s:config_Get(name, ...) dict abort\n  return get(self.GetAll(a:name), -1, a:0 ? a:1 : '')\nendfunction\n\nfunction! s:config_GetRegexp(pattern) dict abort\n  return fugitive#ConfigGetRegexp(self, a:pattern)\nendfunction\n\ncall s:add_methods('config', ['GetAll', 'Get', 'GetRegexp'])\n\nfunction! s:RemoteDefault(dir) abort\n  let head = FugitiveHead(0, a:dir)\n  let remote = len(head) ? FugitiveConfigGet('branch.' . head . '.remote', a:dir) : ''\n  let i = 10\n  while remote ==# '.' && i > 0\n    let head = matchstr(FugitiveConfigGet('branch.' . head . '.merge', a:dir), 'refs/heads/\\zs.*')\n    let remote = len(head) ? FugitiveConfigGet('branch.' . head . '.remote', a:dir) : ''\n    let i -= 1\n  endwhile\n  return remote =~# '^\\.\\=$' ? 'origin' : remote\nendfunction\n\nfunction! s:SshParseHost(value) abort\n  let patterns = []\n  let negates = []\n  for host in split(a:value, '\\s\\+')\n    let pattern = substitute(host, '[\\\\^$.*~?]', '\\=submatch(0) == \"*\" ? \".*\" : submatch(0) == \"?\" ? \".\" : \"\\\\\" . submatch(0)', 'g')\n    if pattern[0] ==# '!'\n      call add(negates, '\\&\\%(^' . pattern[1 : -1] . '$\\)\\@!')\n    else\n      call add(patterns, pattern)\n    endif\n  endfor\n  return '^\\%(' . join(patterns, '\\|') . '\\)$' . join(negates, '')\nendfunction\n\nfunction! s:SshParseConfig(into, root, file) abort\n  try\n    let lines = readfile(a:file)\n  catch\n    return a:into\n  endtry\n  let host = '^\\%(.*\\)$'\n  while !empty(lines)\n    let line = remove(lines, 0)\n    let key = tolower(matchstr(line, '^\\s*\\zs\\w\\+\\ze\\s'))\n    let value = matchstr(line, '^\\s*\\w\\+\\s\\+\\zs.*\\S')\n    if key ==# 'match'\n      let host = value ==# 'all' ? '^\\%(.*\\)$' : ''\n    elseif key ==# 'host'\n      let host = s:SshParseHost(value)\n    elseif key ==# 'include'\n      for glob in split(value)\n        if glob !~# '^[~/]'\n          let glob = a:root . glob\n        endif\n        for included in reverse(split(glob(glob), \"\\n\"))\n          try\n            call extend(lines, readfile(included), 'keep')\n          catch\n          endtry\n        endfor\n      endfor\n    elseif len(key) && len(host)\n      call extend(a:into, {key : []}, 'keep')\n      call add(a:into[key], [host, value])\n    endif\n  endwhile\n  return a:into\nendfunction\n\nunlet! s:ssh_config\nfunction! fugitive#SshConfig(host, ...) abort\n  if !exists('s:ssh_config')\n    let s:ssh_config = {}\n    for file in [expand(\"~/.ssh/config\"), \"/etc/ssh/ssh_config\"]\n      call s:SshParseConfig(s:ssh_config, substitute(file, '\\w*$', '', ''), file)\n    endfor\n  endif\n  let host_config = {}\n  for key in a:0 ? a:1 : keys(s:ssh_config)\n    for [host_pattern, value] in get(s:ssh_config, key, [])\n      if a:host =~# host_pattern\n        let host_config[key] = value\n        break\n      endif\n    endfor\n  endfor\n  return host_config\nendfunction\n\nfunction! fugitive#SshHostAlias(authority) abort\n  let [_, user, host, port; __] = matchlist(a:authority, '^\\%(\\([^/@]\\+\\)@\\)\\=\\(.\\{-\\}\\)\\%(:\\(\\d\\+\\)\\)\\=$')\n  let c = fugitive#SshConfig(host, ['user', 'hostname', 'port'])\n  if empty(user)\n    let user = get(c, 'user', '')\n  endif\n  if empty(port)\n    let port = get(c, 'port', '')\n  endif\n  return (len(user) ? user . '@' : '') . get(c, 'hostname', host) . (port =~# '^\\%(22\\)\\=$' ? '' : ':' . port)\nendfunction\n\nfunction! s:CurlResponse(result) abort\n  let a:result.headers = {}\n  for line in a:result.exit_status ? [] : remove(a:result, 'stdout')\n    let header = matchlist(line, '^\\([[:alnum:]-]\\+\\):\\s\\(.\\{-\\}\\)'. \"\\r\\\\=$\")\n    if len(header)\n      let k = tolower(header[1])\n      if has_key(a:result.headers, k)\n        let a:result.headers[k] .= ', ' . header[2]\n      else\n        let a:result.headers[k] = header[2]\n      endif\n    elseif empty(line)\n      break\n    endif\n  endfor\nendfunction\n\nlet s:remote_headers = {}\n\nfunction! fugitive#RemoteHttpHeaders(remote) abort\n  let remote = type(a:remote) ==# type({}) ? get(a:remote, 'remote', '') : a:remote\n  if type(remote) !=# type('') || remote !~# '^https\\=://.' || !s:executable('curl')\n    return {}\n  endif\n  let remote = substitute(remote, '#.*', '', '')\n  if !has_key(s:remote_headers, remote)\n    let url = remote . '/info/refs?service=git-upload-pack'\n    let exec = s:JobExecute(\n          \\ ['curl', '--disable', '--silent', '--max-time', '5', '-X', 'GET', '-I',\n          \\ url], {}, [], [function('s:CurlResponse')], {})\n    call fugitive#Wait(exec)\n    let s:remote_headers[remote] = exec.headers\n  endif\n  return s:remote_headers[remote]\nendfunction\n\nfunction! s:UrlParse(url) abort\n  let scp_authority = matchstr(a:url, '^[^:/]\\+\\ze:\\%(//\\)\\@!')\n  if len(scp_authority) && !(has('win32') && scp_authority =~# '^\\a:[\\/]')\n    let url = {'scheme': 'ssh', 'authority': s:UrlEncode(scp_authority), 'hash': '',\n          \\ 'path': s:UrlEncode(strpart(a:url, len(scp_authority) + 1))}\n  elseif empty(a:url)\n    let url = {'scheme': '', 'authority': '', 'path': '', 'hash': ''}\n  else\n    let match = matchlist(a:url, '^\\([[:alnum:].+-]\\+\\)://\\([^/]*\\)\\(/[^#]*\\)\\=\\(#.*\\)\\=$')\n    if empty(match)\n      let url = {'scheme': 'file', 'authority': '', 'hash': '',\n            \\ 'path': s:UrlEncode(a:url)}\n    else\n      let url = {'scheme': match[1], 'authority': match[2], 'hash': match[4]}\n      let url.path = empty(match[3]) ? '/' : match[3]\n    endif\n  endif\n  return url\nendfunction\n\nfunction! s:UrlPopulate(string, into) abort\n  let url = a:into\n  let url.protocol = substitute(url.scheme, '.\\zs$', ':', '')\n  let url.user = fugitive#UrlDecode(matchstr(url.authority, '.\\{-\\}\\ze@', '', ''))\n  let url.host = substitute(url.authority, '.\\{-\\}@', '', '')\n  let url.hostname = substitute(url.host, ':\\d\\+$', '', '')\n  let url.port = matchstr(url.host, ':\\zs\\d\\+$', '', '')\n  let url.origin = substitute(url.scheme, '.\\zs$', '://', '') . url.host\n  let url.search = matchstr(url.path, '?.*')\n  let url.pathname = '/' . matchstr(url.path, '^/\\=\\zs[^?]*')\n  if (url.scheme ==# 'ssh' || url.scheme ==# 'git') && url.path[0:1] ==# '/~'\n    let url.path = strpart(url.path, 1)\n  endif\n  if url.path =~# '^/'\n    let url.href = url.scheme . '://' . url.authority . url.path . url.hash\n  elseif url.path =~# '^\\~'\n    let url.href = url.scheme . '://' . url.authority . '/' . url.path . url.hash\n  elseif url.scheme ==# 'ssh' && url.authority !~# ':'\n    let url.href = url.authority . ':' . url.path . url.hash\n  else\n    let url.href = a:string\n  endif\n  let url.path = fugitive#UrlDecode(matchstr(url.path, '^[^?]*'))\n  let url.url = matchstr(url.href, '^[^#]*')\nendfunction\n\nfunction! s:RemoteResolve(url, flags) abort\n  let remote = s:UrlParse(a:url)\n  if remote.scheme =~# '^https\\=$' && index(a:flags, ':nohttp') < 0\n    let headers = fugitive#RemoteHttpHeaders(a:url)\n    let loc = matchstr(get(headers, 'location', ''), '^https\\=://.\\{-\\}\\ze/info/refs?')\n    if len(loc)\n      let remote = s:UrlParse(loc)\n    else\n      let remote.headers = headers\n    endif\n  elseif remote.scheme ==# 'ssh'\n    let remote.authority = fugitive#SshHostAlias(remote.authority)\n  endif\n  return remote\nendfunction\n\nfunction! s:ConfigLengthSort(i1, i2) abort\n  return len(a:i2[0]) - len(a:i1[0])\nendfunction\n\nfunction! s:RemoteCallback(config, into, flags, cb) abort\n  if a:into.remote_name =~# '^\\.\\=$'\n    let a:into.remote_name = s:RemoteDefault(a:config)\n  endif\n  let url = a:into.remote_name\n\n  if url ==# '.git'\n    let url = s:GitDir(a:config)\n  elseif url !~# ':\\|^/\\|^\\a:[\\/]\\|^\\.\\.\\=/'\n    let url = FugitiveConfigGet('remote.' . url . '.url', a:config)\n  endif\n  let instead_of = []\n  for [k, vs] in items(fugitive#ConfigGetRegexp('^url\\.\\zs.\\{-\\}\\ze\\.insteadof$', a:config))\n    for v in vs\n      call add(instead_of, [v, k])\n    endfor\n  endfor\n  call sort(instead_of, 's:ConfigLengthSort')\n  for [orig, replacement] in instead_of\n    if strpart(url, 0, len(orig)) ==# orig\n      let url = replacement . strpart(url, len(orig))\n      break\n    endif\n  endfor\n  if index(a:flags, ':noresolve') < 0\n    call extend(a:into, s:RemoteResolve(url, a:flags))\n  else\n    call extend(a:into, s:UrlParse(url))\n  endif\n  call s:UrlPopulate(url, a:into)\n  if len(a:cb)\n    call call(a:cb[0], [a:into] + a:cb[1:-1])\n  endif\nendfunction\n\nfunction! s:Remote(dir, remote, flags, cb) abort\n  let into = {'remote_name': a:remote, 'git_dir': s:GitDir(a:dir)}\n  let config = fugitive#Config(a:dir, function('s:RemoteCallback'), into, a:flags, a:cb)\n  if len(a:cb)\n    return config\n  else\n    call fugitive#Wait(config)\n    return into\n  endif\nendfunction\n\nfunction! s:RemoteParseArgs(args) abort\n  \" Extract ':noresolve' style flags and an optional callback\n  let args = []\n  let flags = []\n  let cb = copy(a:args)\n  while len(cb)\n    if type(cb[0]) ==# type(function('tr'))\n      break\n    elseif len(args) > 1 || type(cb[0]) ==# type('') && cb[0] =~# '^:'\n      call add(flags, remove(cb, 0))\n    else\n      call add(args, remove(cb, 0))\n    endif\n  endwhile\n\n  \" From the remaining 0-2 arguments, extract the remote and Git config\n  let remote = ''\n  if empty(args)\n    let dir_or_config = s:Dir()\n  elseif len(args) == 1 && type(args[0]) ==# type('') && args[0] !~# '^/\\|^\\a:[\\\\/]'\n    let dir_or_config = s:Dir()\n    let remote = args[0]\n  elseif len(args) == 1\n    let dir_or_config = args[0]\n    if type(args[0]) ==# type({}) && has_key(args[0], 'remote_name')\n      let remote = args[0].remote_name\n    endif\n  elseif type(args[1]) !=# type('') || args[1] =~# '^/\\|^\\a:[\\\\/]'\n    let dir_or_config = args[1]\n    let remote = args[0]\n  else\n    let dir_or_config = args[0]\n    let remote = args[1]\n  endif\n  return [dir_or_config, remote, flags, cb]\nendfunction\n\nfunction! fugitive#Remote(...) abort\n  let [dir_or_config, remote, flags, cb] = s:RemoteParseArgs(a:000)\n  return s:Remote(dir_or_config, remote, flags, cb)\nendfunction\n\nfunction! s:RemoteUrlCallback(remote, callback) abort\n  return call(a:callback[0], [a:remote.url] + a:callback[1:-1])\nendfunction\n\nfunction! fugitive#RemoteUrl(...) abort\n  let [dir_or_config, remote_url, flags, cb] = s:RemoteParseArgs(a:000)\n  if len(cb)\n    let cb = [function('s:RemoteUrlCallback'), cb]\n  endif\n  let remote = s:Remote(dir_or_config, remote_url, flags, cb)\n  return get(remote, 'url', remote_url)\nendfunction\n\n\" Section: Quickfix\n\nfunction! s:QuickfixGet(nr, ...) abort\n  if a:nr < 0\n    return call('getqflist', a:000)\n  else\n    return call('getloclist', [a:nr] + a:000)\n  endif\nendfunction\n\nfunction! s:QuickfixSet(nr, ...) abort\n  if a:nr < 0\n    return call('setqflist', a:000)\n  else\n    return call('setloclist', [a:nr] + a:000)\n  endif\nendfunction\n\nfunction! s:QuickfixCreate(nr, opts) abort\n  if has('patch-7.4.2200')\n    call s:QuickfixSet(a:nr, [], ' ', a:opts)\n  else\n    call s:QuickfixSet(a:nr, [], ' ')\n  endif\nendfunction\n\nfunction! s:QuickfixOpen(nr, mods) abort\n  let mods = substitute(s:Mods(a:mods), '\\<\\d*tab\\>', '', '')\n  return mods . (a:nr < 0 ? 'c' : 'l').'open' . (mods =~# '\\<vertical\\>' ? ' 20' : '')\nendfunction\n\nfunction! s:QuickfixStream(nr, event, title, cmd, first, mods, callback, ...) abort\n  call s:BlurStatus()\n  let opts = {'title': a:title, 'context': {'items': []}}\n  call s:QuickfixCreate(a:nr, opts)\n  let event = (a:nr < 0 ? 'c' : 'l') . 'fugitive-' . a:event\n  exe s:DoAutocmd('QuickFixCmdPre ' . event)\n  let winnr = winnr()\n  exe s:QuickfixOpen(a:nr, a:mods)\n  if winnr != winnr()\n    wincmd p\n  endif\n\n  let buffer = []\n  let lines = s:SystemList(a:cmd)[0]\n  for line in lines\n    call extend(buffer, call(a:callback, a:000 + [line]))\n    if len(buffer) >= 20\n      let contexts = map(copy(buffer), 'get(v:val, \"context\", {})')\n      lockvar contexts\n      call extend(opts.context.items, contexts)\n      unlet contexts\n      call s:QuickfixSet(a:nr, remove(buffer, 0, -1), 'a')\n      if a:mods !~# '\\<silent\\>'\n        redraw\n      endif\n    endif\n  endfor\n  call extend(buffer, call(a:callback, a:000 + [0]))\n  call extend(opts.context.items, map(copy(buffer), 'get(v:val, \"context\", {})'))\n  lockvar opts.context.items\n  call s:QuickfixSet(a:nr, buffer, 'a')\n\n  exe s:DoAutocmd('QuickFixCmdPost ' . event)\n  if a:first\n    let list = s:QuickfixGet(a:nr)\n    for index in range(len(list))\n      if list[index].valid\n        return (index+1) . (a:nr < 0 ? 'cfirst' : 'lfirst')\n      endif\n    endfor\n  endif\n  return 'exe'\nendfunction\n\nfunction! fugitive#Cwindow() abort\n  if &buftype == 'quickfix'\n    cwindow\n  else\n    botright cwindow\n    if &buftype == 'quickfix'\n      wincmd p\n    endif\n  endif\nendfunction\n\n\" Section: Repository Object\n\nlet s:repo_prototype = {}\n\nfunction! fugitive#repo(...) abort\n  let dir = a:0 ? s:GitDir(a:1) : (len(s:GitDir()) ? s:GitDir() : FugitiveExtractGitDir(expand('%:p')))\n  if dir !=# ''\n    return extend({'git_dir': dir, 'fugitive_dir': dir}, s:repo_prototype, 'keep')\n  endif\n  throw 'fugitive: not a Git repository'\nendfunction\n\nfunction! s:repo_dir(...) dict abort\n  if !a:0\n    return self.git_dir\n  endif\n  throw 'fugitive: fugitive#repo().dir(\"...\") has been replaced by FugitiveFind(\".git/...\")'\nendfunction\n\nfunction! s:repo_tree(...) dict abort\n  let tree = s:Tree(self.git_dir)\n  if empty(tree)\n    throw 'fugitive: no work tree'\n  elseif !a:0\n    return tree\n  endif\n  throw 'fugitive: fugitive#repo().tree(\"...\") has been replaced by FugitiveFind(\":(top)...\")'\nendfunction\n\nfunction! s:repo_bare() dict abort\n  throw 'fugitive: fugitive#repo().bare() has been replaced by !empty(FugitiveWorkTree())'\nendfunction\n\nfunction! s:repo_find(object) dict abort\n  throw 'fugitive: fugitive#repo().find(...) has been replaced by FugitiveFind(...)'\nendfunction\n\nfunction! s:repo_translate(rev) dict abort\n  throw 'fugitive: fugitive#repo().translate(...) has been replaced by FugitiveFind(...)'\nendfunction\n\nfunction! s:repo_head(...) dict abort\n  throw 'fugitive: fugitive#repo().head(...) has been replaced by FugitiveHead(...)'\nendfunction\n\ncall s:add_methods('repo',['dir','tree','bare','find','translate','head'])\n\nfunction! s:repo_git_command(...) dict abort\n  throw 'fugitive: fugitive#repo().git_command(...) has been replaced by FugitiveShellCommand(...)'\nendfunction\n\nfunction! s:repo_git_chomp(...) dict abort\n  silent return substitute(system(fugitive#ShellCommand(a:000, self.git_dir)), '\\n$', '', '')\nendfunction\n\nfunction! s:repo_git_chomp_in_tree(...) dict abort\n  return call(self.git_chomp, a:000, self)\nendfunction\n\nfunction! s:repo_rev_parse(rev) dict abort\n  throw 'fugitive: fugitive#repo().rev_parse(...) has been replaced by FugitiveExecute(\"rev-parse\", \"--verify\", ...).stdout'\nendfunction\n\ncall s:add_methods('repo',['git_command','git_chomp','git_chomp_in_tree','rev_parse'])\n\nfunction! s:repo_config(name) dict abort\n  return FugitiveConfigGet(a:name, self.git_dir)\nendfunction\n\ncall s:add_methods('repo',['config'])\n\n\" Section: File API\n\nfunction! s:DirCommitFile(path) abort\n  let vals = matchlist(s:Slash(a:path), s:dir_commit_file)\n  if empty(vals)\n    return ['', '', '']\n  endif\n  return [s:Dir(fugitive#UrlDecode(vals[1])), vals[2], empty(vals[2]) ? '/.git/index' : fugitive#UrlDecode(vals[3])]\nendfunction\n\nfunction! s:DirRev(url) abort\n  let [dir, commit, file] = s:DirCommitFile(a:url)\n  return [dir, commit . file ==# '/.git/index' ? ':' : (!empty(dir) && commit =~# '^.$' ? ':' : '') . commit . substitute(file, '^/', ':', '')]\nendfunction\n\nfunction! fugitive#Parse(url) abort\n  return reverse(s:DirRev(a:url))\nendfunction\n\nlet s:merge_heads = ['MERGE_HEAD', 'REBASE_HEAD', 'CHERRY_PICK_HEAD', 'REVERT_HEAD']\nfunction! s:MergeHead(dir) abort\n  let dir = fugitive#Find('.git/', a:dir)\n  for head in s:merge_heads\n    if filereadable(dir . head)\n      return head\n    endif\n  endfor\n  return ''\nendfunction\n\nfunction! s:Owner(path, ...) abort\n  let dir = a:0 ? s:Dir(a:1) : s:Dir()\n  if empty(dir)\n    return ''\n  endif\n  let actualdir = fugitive#Find('.git/', dir)\n  let [pdir, commit, file] = s:DirCommitFile(a:path)\n  if s:SameRepo(dir, pdir)\n    if commit =~# '^\\x\\{40,\\}$'\n      return commit\n    elseif commit ==# '2'\n      return '@'\n    elseif commit ==# '0'\n      return ''\n    endif\n    let merge_head = s:MergeHead(dir)\n    if empty(merge_head)\n      return ''\n    endif\n    if commit ==# '3'\n      return merge_head\n    elseif commit ==# '1'\n      return s:TreeChomp('merge-base', 'HEAD', merge_head, '--')\n    endif\n  endif\n  let path = fnamemodify(a:path, ':p')\n  if s:cpath(actualdir, strpart(path, 0, len(actualdir))) && a:path =~# 'HEAD$'\n    return strpart(path, len(actualdir))\n  endif\n  let refs = fugitive#Find('.git/refs', dir)\n  if s:cpath(refs . '/', path[0 : len(refs)]) && path !~# '[\\/]$'\n    return strpart(path, len(refs) - 4)\n  endif\n  return ''\nendfunction\n\nfunction! fugitive#Real(url) abort\n  if empty(a:url)\n    return ''\n  endif\n  let [dir, commit, file] = s:DirCommitFile(a:url)\n  if len(dir)\n    let tree = s:Tree(dir)\n    return s:VimSlash((len(tree) ? tree : s:GitDir(dir)) . file)\n  endif\n  let pre = substitute(matchstr(a:url, '^\\a\\a\\+\\ze:'), '^.', '\\u&', '')\n  if len(pre) && pre !=? 'fugitive' && exists('*' . pre . 'Real')\n    let url = {pre}Real(a:url)\n  else\n    let url = fnamemodify(a:url, ':p' . (a:url =~# '[\\/]$' ? '' : ':s?[\\/]$??'))\n  endif\n  return s:VimSlash(empty(url) ? a:url : url)\nendfunction\n\nfunction! fugitive#Path(url, ...) abort\n  if empty(a:url)\n    return ''\n  endif\n  let repo = call('s:Dir', a:000[1:-1])\n  let dir_s = fugitive#Find('.git/', repo)\n  let tree = fugitive#Find(':/', repo)\n  if !a:0\n    return fugitive#Real(a:url)\n  elseif a:1 =~# '\\.$'\n    let path = s:Slash(fugitive#Real(a:url))\n    let cwd = getcwd()\n    let lead = ''\n    while s:cpath(tree . '/', (cwd . '/')[0 : len(tree)])\n      if s:cpath(cwd . '/', path[0 : len(cwd)])\n        if strpart(path, len(cwd) + 1) =~# '^\\.git\\%(/\\|$\\)'\n          break\n        endif\n        return a:1[0:-2] . (empty(lead) ? './' : lead) . strpart(path, len(cwd) + 1)\n      endif\n      let cwd = fnamemodify(cwd, ':h')\n      let lead .= '../'\n    endwhile\n    return a:1[0:-2] . path\n  endif\n  let url = a:url\n  let temp_state = s:TempState(url)\n  if has_key(temp_state, 'origin_bufnr')\n    let url = bufname(temp_state.origin_bufnr)\n  endif\n  let url = s:Slash(fnamemodify(url, ':p'))\n  if url =~# '/$' && s:Slash(a:url) !~# '/$'\n    let url = url[0:-2]\n  endif\n  let [argdir, commit, file] = s:DirCommitFile(url)\n  if !empty(argdir) && !s:SameRepo(argdir, repo)\n    let file = ''\n  elseif len(dir_s) && s:cpath(strpart(url, 0, len(dir_s)), dir_s)\n    let file = '/.git' . strpart(url, len(dir_s)-1)\n  elseif len(tree) && s:cpath(url[0 : len(tree)]) ==# s:cpath(tree . '/')\n    let file = url[len(tree) : -1]\n  elseif s:cpath(url) ==# s:cpath(tree)\n    let file = '/'\n  endif\n  if empty(file) && a:1 =~# '^$\\|^[.:]/$'\n    return FugitiveGitPath(fugitive#Real(a:url))\n  endif\n  return substitute(file, '^/', '\\=a:1', '')\nendfunction\n\nfunction! s:Relative(...) abort\n  return fugitive#Path(@%, a:0 ? a:1 : ':(top)', a:0 > 1 ? a:2 : s:Dir())\nendfunction\n\nfunction! fugitive#Find(object, ...) abort\n  if type(a:object) == type(0)\n    let name = bufname(a:object)\n    return s:VimSlash(name =~# '^$\\|^/\\|^\\a\\+:' ? name : getcwd() . '/' . name)\n  elseif a:object =~# '^[~$]'\n    let prefix = matchstr(a:object, '^[~$]\\i*')\n    let owner = expand(prefix)\n    return s:VimSlash(FugitiveVimPath((len(owner) ? owner : prefix) . strpart(a:object, len(prefix))))\n  endif\n  let rev = s:Slash(a:object)\n  if rev =~# '^\\a\\+://' && rev !~# '^fugitive:'\n    return rev\n  elseif rev =~# '^$\\|^/\\|^\\%(\\a\\a\\+:\\).*\\%(//\\|::\\)' . (has('win32') ? '\\|^\\a:/' : '')\n    return s:VimSlash(a:object)\n  elseif rev =~# '^\\.\\.\\=\\%(/\\|$\\)'\n    return s:VimSlash(simplify(getcwd() . '/' . a:object))\n  endif\n  let dir = call('s:GitDir', a:000)\n  if empty(dir)\n    let file = matchstr(a:object, '^\\%(:\\d:\\|[^:]*:\\)\\zs\\%(\\.\\.\\=$\\|\\.\\.\\=/.*\\|/.*\\|\\w:/.*\\)')\n    let dir = FugitiveExtractGitDir(file)\n    if empty(dir)\n      return ''\n    endif\n  endif\n  let tree = s:Tree(dir)\n  let urlprefix = s:DirUrlPrefix(dir)\n  let base = len(tree) ? tree : urlprefix . '0'\n  if rev ==# '.git'\n    let f = len(tree) && len(getftype(tree . '/.git')) ? tree . '/.git' : dir\n  elseif rev =~# '^\\.git/'\n    let f = strpart(rev, 5)\n    let fdir = simplify(FugitiveActualDir(dir) . '/')\n    let cdir = simplify(FugitiveCommonDir(dir) . '/')\n    if f =~# '^\\.\\./\\.\\.\\%(/\\|$\\)'\n      let f = simplify(len(tree) ? tree . f[2:-1] : fdir . f)\n    elseif f =~# '^\\.\\.\\%(/\\|$\\)'\n      let f = s:PathJoin(base, f[2:-1])\n    elseif cdir !=# fdir && (\n          \\ f =~# '^\\%(config\\|hooks\\|info\\|logs/refs\\|objects\\|refs\\|worktrees\\)\\%(/\\|$\\)' ||\n          \\ f !~# '^\\%(index$\\|index\\.lock$\\|\\w*MSG$\\|\\w*HEAD$\\|logs/\\w*HEAD$\\|logs$\\|rebase-\\w\\+\\)\\%(/\\|$\\)' &&\n          \\ getftime(fdir . f) < 0 && getftime(cdir . f) >= 0)\n      let f = simplify(cdir . f)\n    else\n      let f = simplify(fdir . f)\n    endif\n  elseif rev ==# ':/'\n    let f = tree\n  elseif rev =~# '^\\.\\%(/\\|$\\)'\n    let f = s:PathJoin(base, rev[1:-1])\n  elseif rev =~# '^::\\%(/\\|\\a\\+\\:\\)'\n    let f = rev[2:-1]\n  elseif rev =~# '^::\\.\\.\\=\\%(/\\|$\\)'\n    let f = simplify(getcwd() . '/' . rev[2:-1])\n  elseif rev =~# '^::'\n    let f = s:PathJoin(base, '/' . rev[2:-1])\n  elseif rev =~# '^:\\%([0-3]:\\)\\=\\.\\.\\=\\%(/\\|$\\)\\|^:[0-3]:\\%(/\\|\\a\\+:\\)'\n    let f = rev =~# '^:\\%([0-3]:\\)\\=\\.' ? simplify(getcwd() . '/' . matchstr(rev, '\\..*')) : rev[3:-1]\n    if s:cpath(base . '/', (f . '/')[0 : len(base)])\n      let f = s:PathJoin(urlprefix, +matchstr(rev, '^:\\zs\\d\\ze:') . '/' . strpart(f, len(base) + 1))\n    else\n      let altdir = FugitiveExtractGitDir(f)\n      if len(altdir) && !s:cpath(dir, altdir)\n        return fugitive#Find(a:object, altdir)\n      endif\n    endif\n  elseif rev =~# '^:[0-3]:'\n    let f = s:PathJoin(urlprefix, rev[1] . '/' . rev[3:-1])\n  elseif rev ==# ':'\n    let f = urlprefix\n  elseif rev =~# '^:(\\%(top\\|top,literal\\|literal,top\\|literal\\))'\n    let f = matchstr(rev, ')\\zs.*')\n    if f=~# '^\\.\\.\\=\\%(/\\|$\\)'\n      let f = simplify(getcwd() . '/' . f)\n    elseif f !~# '^/\\|^\\%(\\a\\a\\+:\\).*\\%(//\\|::\\)' . (has('win32') ? '\\|^\\a:/' : '')\n      let f = s:PathJoin(base, '/' . f)\n    endif\n  elseif rev =~# '^:/\\@!'\n    let f = s:PathJoin(urlprefix, '0/' . rev[1:-1])\n  else\n    if !exists('f')\n      let commit = matchstr(rev, '^\\%([^:.-]\\|\\.\\.[^/:]\\)[^:]*\\|^:.*')\n      let file = substitute(matchstr(rev, '^\\%([^:.-]\\|\\.\\.[^/:]\\)[^:]*\\zs:.*'), '^:', '/', '')\n      if file =~# '^/\\.\\.\\=\\%(/\\|$\\)\\|^//\\|^/\\a\\+:'\n        let file = file =~# '^/\\.' ? simplify(getcwd() . file) : file[1:-1]\n        if s:cpath(base . '/', (file . '/')[0 : len(base)])\n          let file = '/' . strpart(file, len(base) + 1)\n        else\n          let altdir = FugitiveExtractGitDir(file)\n          if len(altdir) && !s:cpath(dir, altdir)\n            return fugitive#Find(a:object, altdir)\n          endif\n          return file\n        endif\n      endif\n      let commits = split(commit, '\\.\\.\\.-\\@!', 1)\n      if len(commits) == 2\n        call map(commits, 'empty(v:val) ? \"@\" : v:val')\n        let commit = matchstr(s:ChompDefault('', [dir, 'merge-base'] + commits + ['--']), '\\<[0-9a-f]\\{40,\\}\\>')\n      endif\n      if commit !~# '^[0-9a-f]\\{40,\\}$\\|^$'\n        let commit = matchstr(s:ChompDefault('', [dir, 'rev-parse', '--verify', commit . (len(file) ? '^{}' : ''), '--']), '\\<[0-9a-f]\\{40,\\}\\>')\n        if empty(commit) && len(file)\n          let commit = repeat('0', 40)\n        endif\n      endif\n      if len(commit)\n        let f = s:PathJoin(urlprefix, commit . file)\n      else\n        let f = s:PathJoin(base, '/' . substitute(rev, '^:/:\\=\\|^[^:]\\+:', '', ''))\n      endif\n    endif\n  endif\n  return s:VimSlash(f)\nendfunction\n\nfunction! s:Generate(object, ...) abort\n  let dir = a:0 ? a:1 : s:Dir()\n  let f = fugitive#Find(a:object, dir)\n  if !empty(f)\n    return f\n  elseif a:object ==# ':/'\n    return len(dir) ? s:VimSlash(s:DirUrlPrefix(dir) . '0') : '.'\n  endif\n  let file = matchstr(a:object, '^\\%(:\\d:\\|[^:]*:\\)\\=\\zs.*')\n  return empty(file) ? '' : fnamemodify(s:VimSlash(file), ':p')\nendfunction\n\nfunction! s:DotRelative(path, ...) abort\n  let cwd = a:0 ? a:1 : getcwd()\n  let path = substitute(a:path, '^[~$]\\i*', '\\=expand(submatch(0))', '')\n  if len(cwd) && s:cpath(cwd . '/', (path . '/')[0 : len(cwd)])\n    return '.' . strpart(path, len(cwd))\n  endif\n  return a:path\nendfunction\n\nfunction! fugitive#Object(...) abort\n  let dir = a:0 > 1 ? s:Dir(a:2) : s:Dir()\n  let [fdir, rev] = s:DirRev(a:0 ? a:1 : @%)\n  if !s:SameRepo(dir, fdir)\n    let rev = ''\n  endif\n  let tree = s:Tree(dir)\n  let full = a:0 ? a:1 : s:BufName('%')\n  let full = fnamemodify(full, ':p' . (s:Slash(full) =~# '/$' ? '' : ':s?/$??'))\n  if empty(rev) && empty(tree)\n    return FugitiveGitPath(full)\n  elseif empty(rev)\n    let rev = fugitive#Path(full, './', dir)\n    if rev =~# '^\\./.git\\%(/\\|$\\)'\n      return FugitiveGitPath(full)\n    endif\n  endif\n  if rev !~# '^\\.\\%(/\\|$\\)' || s:cpath(getcwd(), tree)\n    return rev\n  else\n    return FugitiveGitPath(tree . rev[1:-1])\n  endif\nendfunction\n\nlet s:var = '\\%(<\\%(cword\\|cWORD\\|cexpr\\|cfile\\|sfile\\|slnum\\|afile\\|abuf\\|amatch' . (has('clientserver') ? '\\|client' : '') . '\\)>\\|%\\|#<\\=\\d\\+\\|##\\=\\)'\nlet s:flag = '\\%(:[p8~.htre]\\|:g\\=s\\(.\\).\\{-\\}\\1.\\{-\\}\\1\\)'\nlet s:expand = '\\%(\\(' . s:var . '\\)\\(' . s:flag . '*\\)\\(:S\\)\\=\\)'\nlet s:commit_expand = '!\\\\\\@!#\\=\\d*\\|!%'\n\nfunction! s:BufName(var) abort\n  if a:var ==# '%'\n    return bufname(get(s:TempState(), 'origin_bufnr', ''))\n  elseif a:var =~# '^#\\d*$'\n    let nr = get(s:TempState(+a:var[1:-1]), 'origin_bufnr', '')\n    return bufname(nr ? nr : +a:var[1:-1])\n  else\n    return expand(a:var)\n  endif\nendfunction\n\nfunction! s:ExpandVar(other, var, flags, esc, ...) abort\n  let cwd = a:0 ? a:1 : getcwd()\n  if a:other =~# '^\\'\n    return a:other[1:-1]\n  elseif a:other =~# '^'''\n    return substitute(a:other[1:-2], \"''\", \"'\", \"g\")\n  elseif a:other =~# '^\"'\n    return substitute(a:other[1:-2], '\"\"', '\"', \"g\")\n  elseif a:other =~# '^[!`]'\n    let buffer = s:BufName(a:other =~# '[0-9#]' ? '#' . matchstr(a:other, '\\d\\+') : '%')\n    let owner = s:Owner(buffer)\n    return len(owner) ? owner : '@'\n  elseif a:other =~# '^\\~[~.]$'\n    return s:Slash(getcwd())\n  elseif len(a:other)\n    return expand(a:other)\n  elseif a:var ==# '<cfile>'\n    let bufnames = [expand('<cfile>')]\n    if get(maparg('<Plug><cfile>', 'c', 0, 1), 'expr')\n      try\n        let bufnames = [eval(maparg('<Plug><cfile>', 'c'))]\n        if bufnames[0] ==# \"\\<C-R>\\<C-F>\"\n          let bufnames = [expand('<cfile>')]\n        endif\n      catch\n      endtry\n    endif\n  elseif a:var =~# '^<'\n    let bufnames = [s:BufName(a:var)]\n  elseif a:var ==# '##'\n    let bufnames = map(argv(), 'fugitive#Real(v:val)')\n  else\n    let bufnames = [fugitive#Real(s:BufName(a:var))]\n  endif\n  let files = []\n  for bufname in bufnames\n    let flags = a:flags\n    let file = s:DotRelative(bufname, cwd)\n    while len(flags)\n      let flag = matchstr(flags, s:flag)\n      let flags = strpart(flags, len(flag))\n      if flag ==# ':.'\n        let file = s:DotRelative(fugitive#Real(file), cwd)\n      else\n        let file = fnamemodify(file, flag)\n      endif\n    endwhile\n    let file = s:Slash(file)\n    if file =~# '^fugitive://'\n      let [dir, commit, file_candidate] = s:DirCommitFile(file)\n      let tree = s:Tree(dir)\n      if len(tree) && len(file_candidate)\n        let file = (commit =~# '^.$' ? ':' : '') . commit . ':' .\n              \\ s:DotRelative(tree . file_candidate)\n      elseif empty(file_candidate) && commit !~# '^.$'\n        let file = commit\n      endif\n    endif\n    call add(files, len(a:esc) ? shellescape(file) : file)\n  endfor\n  return join(files, \"\\1\")\nendfunction\n\nif has('win32')\n  let s:fnameescape = \" \\t\\n*?`%#'\\\"|!<\"\nelse\n  let s:fnameescape = \" \\t\\n*?[{`$\\\\%#'\\\"|!<\"\nendif\n\nfunction! s:Expand(rev, ...) abort\n  if a:rev =~# '^>' && s:Slash(@%) =~# '^fugitive://' && empty(s:DirCommitFile(@%)[1])\n    return s:Slash(@%)\n  elseif a:rev =~# '^>\\=:[0-3]$'\n    let file = len(expand('%')) ? a:rev[-2:-1] . ':%' : '%'\n  elseif a:rev =~# '^>\\%(:\\=/\\)\\=$'\n    let file = '%'\n  elseif a:rev =~# '^>[> ]\\@!' && @% !~# '^fugitive:' && s:Slash(@%) =~# '://\\|^$'\n    let file = '%'\n  elseif a:rev ==# '>:'\n    let file = empty(s:DirCommitFile(@%)[0]) ? ':0:%' : '%'\n  elseif a:rev =~# '^>[> ]\\@!'\n    let rev = (a:rev =~# '^>[~^]' ? '!' : '') . a:rev[1:-1]\n    let prefix = matchstr(rev, '^\\%(\\\\.\\|{[^{}]*}\\|[^:]\\)*')\n    if prefix !=# rev\n      let file = rev\n    else\n      let file = len(expand('%')) ? rev . ':%' : '%'\n    endif\n  elseif s:Slash(a:rev) =~# '^\\a\\a\\+://'\n    let file = substitute(a:rev, '\\\\\\@<!\\%(#\\a\\|%\\x\\x\\)', '\\\\&', 'g')\n  elseif a:rev =~# '^:[!#%$]'\n    let file = ':0' . a:rev\n  else\n    let file = a:rev\n  endif\n  return substitute(file,\n        \\ '\\(\\\\[' . s:fnameescape . ']\\|^\\\\[>+-]\\|' . s:commit_expand . '\\|^\\~[~.]\\)\\|' . s:expand,\n        \\ '\\=tr(s:ExpandVar(submatch(1),submatch(2),submatch(3),\"\", a:0 ? a:1 : getcwd()), \"\\1\", \" \")', 'g')\nendfunction\n\nfunction! fugitive#Expand(object) abort\n  return substitute(a:object,\n        \\ '\\(\\\\[' . s:fnameescape . ']\\|^\\\\[>+-]\\|' . s:commit_expand . '\\|^\\~[~.]\\)\\|' . s:expand,\n        \\ '\\=tr(s:ExpandVar(submatch(1),submatch(2),submatch(3),submatch(5)), \"\\1\", \" \")', 'g')\nendfunction\n\nfunction! s:SplitExpandChain(string, ...) abort\n  let list = []\n  let string = a:string\n  let dquote = '\"\\%([^\"]\\|\"\"\\|\\\\\"\\)*\"\\|'\n  let cwd = a:0 ? a:1 : getcwd()\n  while string =~# '\\S'\n    if string =~# '^\\s*|'\n      return [list, substitute(string, '^\\s*', '', '')]\n    endif\n    let arg = matchstr(string, '^\\s*\\%(' . dquote . '''[^'']*''\\|\\\\.\\|[^' . \"\\t\" . ' |]\\)\\+')\n    let string = strpart(string, len(arg))\n    let arg = substitute(arg, '^\\s\\+', '', '')\n    if !exists('seen_separator')\n      let arg = substitute(arg, '^\\%([^:.][^:]*:\\|^:\\%((literal)\\)\\=\\|^:[0-3]:\\)\\=\\zs\\.\\.\\=\\%(/.*\\)\\=$',\n            \\ '\\=s:DotRelative(s:Slash(simplify(getcwd() . \"/\" . submatch(0))), cwd)', '')\n    endif\n    let arg = substitute(arg,\n          \\ '\\(' . dquote . '''\\%(''''\\|[^'']\\)*''\\|\\\\[' . s:fnameescape . ']\\|^\\\\[>+-]\\|' . s:commit_expand . '\\|^\\~[~]\\|^\\~\\w*\\|\\$\\w\\+\\)\\|' . s:expand,\n          \\ '\\=s:ExpandVar(submatch(1),submatch(2),submatch(3),submatch(5), cwd)', 'g')\n    call extend(list, split(arg, \"\\1\", 1))\n    if arg ==# '--'\n      let seen_separator = 1\n    endif\n  endwhile\n  return [list, '']\nendfunction\n\nlet s:trees = {}\nlet s:indexes = {}\nfunction! s:TreeInfo(dir, commit) abort\n  let key = s:GitDir(a:dir)\n  if a:commit =~# '^:\\=[0-3]$'\n    let index = get(s:indexes, key, [])\n    let newftime = getftime(fugitive#Find('.git/index', a:dir))\n    if get(index, 0, -2) < newftime\n      let [lines, exec_error] = s:LinesError([a:dir, 'ls-files', '--stage', '--'])\n      let s:indexes[key] = [newftime, {'0': {}, '1': {}, '2': {}, '3': {}}]\n      if exec_error\n        return [{}, -1]\n      endif\n      for line in lines\n        let [info, filename] = split(line, \"\\t\")\n        let [mode, sha, stage] = split(info, '\\s\\+')\n        let s:indexes[key][1][stage][filename] = [newftime, mode, 'blob', sha, -2]\n        while filename =~# '/'\n          let filename = substitute(filename, '/[^/]*$', '', '')\n          let s:indexes[key][1][stage][filename] = [newftime, '040000', 'tree', '', 0]\n        endwhile\n      endfor\n    endif\n    return [get(s:indexes[key][1], a:commit[-1:-1], {}), newftime]\n  elseif a:commit =~# '^\\x\\{40,\\}$'\n    if !has_key(s:trees, key)\n      let s:trees[key] = {}\n    endif\n    if !has_key(s:trees[key], a:commit)\n      let ftime = s:ChompDefault('', [a:dir, 'log', '-1', '--pretty=format:%ct', a:commit, '--'])\n      if empty(ftime)\n        let s:trees[key][a:commit] = [{}, -1]\n        return s:trees[key][a:commit]\n      endif\n      let s:trees[key][a:commit] = [{}, +ftime]\n      let [lines, exec_error] = s:LinesError([a:dir, 'ls-tree', '-rtl', '--full-name', a:commit, '--'])\n      if exec_error\n        return s:trees[key][a:commit]\n      endif\n      for line in lines\n        let [info, filename] = split(line, \"\\t\")\n        let [mode, type, sha, size] = split(info, '\\s\\+')\n        let s:trees[key][a:commit][0][filename] = [+ftime, mode, type, sha, +size, filename]\n      endfor\n    endif\n    return s:trees[key][a:commit]\n  endif\n  return [{}, -1]\nendfunction\n\nfunction! s:PathInfo(url) abort\n  let [dir, commit, file] = s:DirCommitFile(a:url)\n  if empty(dir) || !get(g:, 'fugitive_file_api', 1)\n    return [-1, '000000', '', '', -1]\n  endif\n  let path = substitute(file[1:-1], '/*$', '', '')\n  let [tree, ftime] = s:TreeInfo(dir, commit)\n  let entry = empty(path) ? [ftime, '040000', 'tree', '', -1] : get(tree, path, [])\n  if empty(entry) || file =~# '/$' && entry[2] !=# 'tree'\n    return [-1, '000000', '', '', -1]\n  else\n    return entry\n  endif\nendfunction\n\nfunction! fugitive#simplify(url) abort\n  let [dir, commit, file] = s:DirCommitFile(a:url)\n  if empty(dir)\n    return ''\n  elseif empty(commit)\n    return s:VimSlash(s:DirUrlPrefix(simplify(s:GitDir(dir))))\n  endif\n  if file =~# '/\\.\\.\\%(/\\|$\\)'\n    let tree = s:Tree(dir)\n    if len(tree)\n      let path = simplify(tree . file)\n      if strpart(path . '/', 0, len(tree) + 1) !=# tree . '/'\n        return s:VimSlash(path)\n      endif\n    endif\n  endif\n  return s:VimSlash(s:PathJoin(s:DirUrlPrefix(simplify(s:GitDir(dir))), commit . simplify(file)))\nendfunction\n\nfunction! fugitive#resolve(url) abort\n  let url = fugitive#simplify(a:url)\n  if url =~? '^fugitive:'\n    return url\n  else\n    return resolve(url)\n  endif\nendfunction\n\nfunction! fugitive#getftime(url) abort\n  return s:PathInfo(a:url)[0]\nendfunction\n\nfunction! fugitive#getfsize(url) abort\n  let entry = s:PathInfo(a:url)\n  if entry[4] == -2 && entry[2] ==# 'blob' && len(entry[3])\n    let dir = s:DirCommitFile(a:url)[0]\n    let entry[4] = +s:ChompDefault(-1, [dir, 'cat-file', '-s', entry[3]])\n  endif\n  return entry[4]\nendfunction\n\nfunction! fugitive#getftype(url) abort\n  return get({'tree': 'dir', 'blob': 'file'}, s:PathInfo(a:url)[2], '')\nendfunction\n\nfunction! fugitive#filereadable(url) abort\n  return s:PathInfo(a:url)[2] ==# 'blob'\nendfunction\n\nfunction! fugitive#filewritable(url) abort\n  let [dir, commit, file] = s:DirCommitFile(a:url)\n  if commit !~# '^\\d$' || !filewritable(fugitive#Find('.git/index', dir))\n    return 0\n  endif\n  return s:PathInfo(a:url)[2] ==# 'blob' ? 1 : 2\nendfunction\n\nfunction! fugitive#isdirectory(url) abort\n  return s:PathInfo(a:url)[2] ==# 'tree'\nendfunction\n\nfunction! fugitive#getfperm(url) abort\n  let [dir, commit, file] = s:DirCommitFile(a:url)\n  let perm = getfperm(dir)\n  let fperm = s:PathInfo(a:url)[1]\n  if fperm ==# '040000'\n    let fperm = '000755'\n  endif\n  if fperm !~# '[15]'\n    let perm = tr(perm, 'x', '-')\n  endif\n  if fperm !~# '[45]$'\n    let perm = tr(perm, 'rw', '--')\n  endif\n  if commit !~# '^\\d$'\n    let perm = tr(perm, 'w', '-')\n  endif\n  return perm ==# '---------' ? '' : perm\nendfunction\n\nfunction! s:UpdateIndex(dir, info) abort\n  let info = join(a:info[0:-2]) . \"\\t\" . a:info[-1] . \"\\n\"\n  let [error, exec_error] = s:StdoutToFile('', [a:dir, 'update-index', '--index-info'], info)\n  return !exec_error ? '' : len(error) ? error : 'unknown update-index error'\nendfunction\n\nfunction! fugitive#setfperm(url, perm) abort\n  let [dir, commit, file] = s:DirCommitFile(a:url)\n  let entry = s:PathInfo(a:url)\n  let perm = fugitive#getfperm(a:url)\n  if commit !~# '^\\d$' || entry[2] !=# 'blob' ||\n      \\ substitute(perm, 'x', '-', 'g') !=# substitute(a:perm, 'x', '-', 'g')\n    return -2\n  endif\n  let error = s:UpdateIndex(dir, [a:perm =~# 'x' ? '000755' : '000644', entry[3], commit, file[1:-1]])\n  return len(error) ? -1 : 0\nendfunction\n\nif !exists('s:blobdirs')\n  let s:blobdirs = {}\nendif\nfunction! s:BlobTemp(url) abort\n  let [dir, commit, file] = s:DirCommitFile(a:url)\n  if empty(file)\n    return ''\n  endif\n  let key = s:GitDir(dir)\n  if !has_key(s:blobdirs, key)\n    let s:blobdirs[key] = tempname()\n  endif\n  let tempfile = s:blobdirs[key] . '/' . commit . file\n  let tempparent = fnamemodify(tempfile, ':h')\n  if !isdirectory(tempparent)\n    call mkdir(tempparent, 'p')\n  elseif isdirectory(tempfile)\n    if commit =~# '^\\d$' && has('patch-7.4.1107')\n      call delete(tempfile, 'rf')\n    else\n      return ''\n    endif\n  endif\n  if commit =~# '^\\d$' || !filereadable(tempfile)\n    let rev = s:DirRev(a:url)[1]\n    let blob_or_filters = fugitive#GitVersion(2, 11) ? '--filters' : 'blob'\n    let exec_error = s:StdoutToFile(tempfile, [dir, 'cat-file', blob_or_filters, rev])[1]\n    if exec_error\n      call delete(tempfile)\n      return ''\n    endif\n  endif\n  return s:Resolve(tempfile)\nendfunction\n\nfunction! fugitive#readfile(url, ...) abort\n  let entry = s:PathInfo(a:url)\n  if entry[2] !=# 'blob'\n    return []\n  endif\n  let temp = s:BlobTemp(a:url)\n  if empty(temp)\n    return []\n  endif\n  return call('readfile', [temp] + a:000)\nendfunction\n\nfunction! fugitive#writefile(lines, url, ...) abort\n  let url = type(a:url) ==# type('') ? a:url : ''\n  let [dir, commit, file] = s:DirCommitFile(url)\n  let entry = s:PathInfo(url)\n  if commit =~# '^\\d$' && entry[2] !=# 'tree'\n    let temp = tempname()\n    if a:0 && a:1 =~# 'a' && entry[2] ==# 'blob'\n      call writefile(fugitive#readfile(url, 'b'), temp, 'b')\n    endif\n    call call('writefile', [a:lines, temp] + a:000)\n    let hash = s:ChompDefault('', [dir, '--literal-pathspecs', 'hash-object', '-w', FugitiveGitPath(temp)])\n    let mode = entry[1] !=# '000000' ? entry[1] : '100644'\n    if hash =~# '^\\x\\{40,\\}$'\n      let error = s:UpdateIndex(dir, [mode, hash, commit, file[1:-1]])\n      if empty(error)\n        return 0\n      endif\n    endif\n  endif\n  return call('writefile', [a:lines, a:url] + a:000)\nendfunction\n\nlet s:globsubs = {\n      \\ '/**/': '/\\%([^./][^/]*/\\)*',\n      \\ '/**': '/\\%([^./][^/]\\+/\\)*[^./][^/]*',\n      \\ '**/': '[^/]*\\%(/[^./][^/]*\\)*',\n      \\ '**': '.*',\n      \\ '/*': '/[^/.][^/]*',\n      \\ '*': '[^/]*',\n      \\ '?': '[^/]'}\nfunction! fugitive#glob(url, ...) abort\n  let [repo, commit, glob] = s:DirCommitFile(a:url)\n  let dirglob = s:GitDir(repo)\n  let append = matchstr(glob, '/*$')\n  let glob = substitute(glob, '/*$', '', '')\n  let pattern = '^' . substitute(glob, '/\\=\\*\\*/\\=\\|/\\=\\*\\|[.?\\$]\\|^^', '\\=get(s:globsubs, submatch(0), \"\\\\\" . submatch(0))', 'g')[1:-1] . '$'\n  let results = []\n  for dir in dirglob =~# '[*?]' ? split(glob(dirglob), \"\\n\") : [dirglob]\n    if empty(dir) || !get(g:, 'fugitive_file_api', 1) || !filereadable(fugitive#Find('.git/HEAD', dir))\n      continue\n    endif\n    let files = items(s:TreeInfo(dir, commit)[0])\n    if len(append)\n      call filter(files, 'v:val[1][2] ==# \"tree\"')\n    endif\n    call map(files, 'v:val[0]')\n    call filter(files, 'v:val =~# pattern')\n    let prepend = s:DirUrlPrefix(dir) . substitute(commit, '^:', '', '') . '/'\n    call sort(files)\n    call map(files, 's:VimSlash(s:PathJoin(prepend, v:val . append))')\n    call extend(results, files)\n  endfor\n  if a:0 > 1 && a:2\n    return results\n  else\n    return join(results, \"\\n\")\n  endif\nendfunction\n\nfunction! fugitive#delete(url, ...) abort\n  let [dir, commit, file] = s:DirCommitFile(a:url)\n  if a:0 && len(a:1) || commit !~# '^\\d$'\n    return -1\n  endif\n  let entry = s:PathInfo(a:url)\n  if entry[2] !=# 'blob'\n    return -1\n  endif\n  let error = s:UpdateIndex(dir, ['000000', '0000000000000000000000000000000000000000', commit, file[1:-1]])\n  return len(error) ? -1 : 0\nendfunction\n\n\" Section: Completion\n\nfunction! s:FilterEscape(items, ...) abort\n  let items = copy(a:items)\n  call map(items, 'fnameescape(v:val)')\n  if !a:0 || type(a:1) != type('')\n    let match = ''\n  else\n    let match = substitute(a:1, '^[+>]\\|\\\\\\@<![' . substitute(s:fnameescape, '\\\\', '', '') . ']', '\\\\&', 'g')\n  endif\n  let cmp = s:FileIgnoreCase(1) ? '==?' : '==#'\n  return filter(items, 'strpart(v:val, 0, strlen(match)) ' . cmp . ' match')\nendfunction\n\nfunction! s:GlobComplete(lead, pattern, ...) abort\n  if a:lead ==# '/'\n    return []\n  else\n    let results = glob(substitute(a:lead . a:pattern, '[\\{}]', '\\\\&', 'g'), a:0 ? a:1 : 0, 1)\n  endif\n  call map(results, 'v:val !~# \"/$\" && isdirectory(v:val) ? v:val.\"/\" : v:val')\n  call map(results, 'v:val[ strlen(a:lead) : -1 ]')\n  return results\nendfunction\n\nfunction! fugitive#CompletePath(base, ...) abort\n  let dir = a:0 == 1 ? a:1 : a:0 >= 3 ? a:3 : s:Dir()\n  let stripped = matchstr(a:base, '^\\%(:/:\\=\\|:(top)\\|:(top,literal)\\|:(literal,top)\\)')\n  let base = strpart(a:base, len(stripped))\n  if len(stripped) || a:0 < 4\n    let root = s:Tree(dir)\n  else\n    let root = a:4\n  endif\n  if root !=# '/' && len(root)\n    let root .= '/'\n  endif\n  if empty(stripped)\n    let stripped = matchstr(a:base, '^\\%(:(literal)\\|:\\)')\n    let base = strpart(a:base, len(stripped))\n  endif\n  if base =~# '^\\.git/' && len(dir)\n    let pattern = s:gsub(base[5:-1], '/', '*&').'*'\n    let fdir = fugitive#Find('.git/', dir)\n    let matches = s:GlobComplete(fdir, pattern)\n    let cdir = fugitive#Find('.git/refs', dir)[0 : -5]\n    if len(cdir) && s:cpath(fdir) !=# s:cpath(cdir)\n      call extend(matches, s:GlobComplete(cdir, pattern))\n    endif\n    call s:Uniq(matches)\n    call map(matches, \"'.git/' . v:val\")\n  elseif base =~# '^\\~/'\n    let matches = map(s:GlobComplete(expand('~/'), base[2:-1] . '*'), '\"~/\" . v:val')\n  elseif a:base =~# '^/\\|^\\a\\+:\\|^\\.\\.\\=/'\n    let matches = s:GlobComplete('', base . '*')\n  elseif len(root)\n    let matches = s:GlobComplete(root, s:gsub(base, '/', '*&').'*')\n  else\n    let matches = []\n  endif\n  call map(matches, 's:fnameescape(s:Slash(stripped . v:val))')\n  return matches\nendfunction\n\nfunction! fugitive#PathComplete(...) abort\n  return call('fugitive#CompletePath', a:000)\nendfunction\n\nfunction! s:CompleteHeads(dir) abort\n  if empty(a:dir)\n    return []\n  endif\n  let dir = fugitive#Find('.git/', a:dir)\n  return sort(filter(['HEAD', 'FETCH_HEAD', 'ORIG_HEAD'] + s:merge_heads, 'filereadable(dir . v:val)')) +\n        \\ sort(s:LinesError([a:dir, 'rev-parse', '--symbolic', '--branches', '--tags', '--remotes'])[0])\nendfunction\n\nfunction! fugitive#CompleteObject(base, ...) abort\n  let dir = a:0 == 1 ? a:1 : a:0 >= 3 ? a:3 : s:Dir()\n  let tree = s:Tree(dir)\n  let cwd = getcwd()\n  let subdir = ''\n  if len(tree) && s:cpath(tree . '/', cwd[0 : len(tree)])\n    let subdir = strpart(cwd, len(tree) + 1) . '/'\n  endif\n  let base = s:Expand(a:base)\n\n  if a:base =~# '^!\\d*$' && base !~# '^!'\n    return [base]\n  elseif base =~# '^\\.\\=/\\|^:(' || base !~# ':'\n    let results = []\n    if base =~# '^refs/'\n      let cdir = fugitive#Find('.git/refs', dir)[0 : -5]\n      let results += map(s:GlobComplete(cdir, base . '*'), 's:Slash(v:val)')\n      call map(results, 's:fnameescape(v:val)')\n    elseif base !~# '^\\.\\=/\\|^:('\n      let heads = s:CompleteHeads(dir)\n      if filereadable(fugitive#Find('.git/refs/stash', dir))\n        let heads += [\"stash\"]\n        let heads += sort(s:LinesError([\"stash\",\"list\",\"--pretty=format:%gd\"], dir)[0])\n      endif\n      let results += s:FilterEscape(heads, fnameescape(base))\n    endif\n    let results += a:0 == 1 || a:0 >= 3 ? fugitive#CompletePath(base, 0, '', dir, a:0 >= 4 ? a:4 : tree) : fugitive#CompletePath(base)\n    return results\n\n  elseif base =~# '^:'\n    let entries = s:LinesError(['ls-files','--stage'], dir)[0]\n    if base =~# ':\\./'\n      call map(entries, 'substitute(v:val, \"\\\\M\\t\\\\zs\" . subdir, \"./\", \"\")')\n    endif\n    call map(entries,'s:sub(v:val,\".*(\\\\d)\\\\t(.*)\",\":\\\\1:\\\\2\")')\n    if base !~# '^:[0-3]\\%(:\\|$\\)'\n      call filter(entries,'v:val[1] == \"0\"')\n      call map(entries,'v:val[2:-1]')\n    endif\n\n  else\n    let parent = matchstr(base, '.*[:/]')\n    let entries = s:LinesError(['ls-tree', substitute(parent,  ':\\zs\\./', '\\=subdir', '')], dir)[0]\n    call map(entries,'s:sub(v:val,\"^04.*\\\\zs$\",\"/\")')\n    call map(entries,'parent.s:sub(v:val,\".*\\t\",\"\")')\n  endif\n  return s:FilterEscape(entries, fnameescape(base))\nendfunction\n\nfunction! s:CompleteSub(subcommand, A, L, P, ...) abort\n  let pre = strpart(a:L, 0, a:P)\n  if pre =~# ' -- '\n    return fugitive#CompletePath(a:A)\n  elseif a:A =~# '^-' || a:A is# 0\n    return s:FilterEscape(split(s:ChompDefault('', [a:subcommand, '--git-completion-helper']), ' '), a:A)\n  elseif !a:0\n    return fugitive#CompleteObject(a:A, s:Dir())\n  elseif type(a:1) == type(function('tr'))\n    return call(a:1, [a:A, a:L, a:P] + (a:0 > 1 ? a:2 : []))\n  else\n    return s:FilterEscape(a:1, a:A)\n  endif\nendfunction\n\nfunction! s:CompleteRevision(A, L, P, ...) abort\n  return s:FilterEscape(s:CompleteHeads(a:0 ? a:1 : s:Dir()), a:A)\nendfunction\n\nfunction! s:CompleteRemote(A, L, P, ...) abort\n  let dir = a:0 ? a:1 : s:Dir()\n  let remote = matchstr(a:L, '\\u\\w*[! ] *.\\{-\\}\\s\\@<=\\zs[^-[:space:]]\\S*\\ze ')\n  if !empty(remote)\n    let matches = s:LinesError([dir, 'ls-remote', remote])[0]\n    call filter(matches, 'v:val =~# \"\\t\" && v:val !~# \"{\"')\n    call map(matches, 's:sub(v:val, \"^.*\\t%(refs/%(heads/|tags/)=)=\", \"\")')\n  else\n    let matches = s:LinesError([dir, 'remote'])[0]\n  endif\n  return s:FilterEscape(matches, a:A)\nendfunction\n\n\" Section: Buffer auto-commands\n\naugroup fugitive_dummy_events\n  autocmd!\n  autocmd User Fugitive* \"\n  autocmd BufWritePre,FileWritePre,FileWritePost * \"\n  autocmd BufNewFile * \"\n  autocmd QuickfixCmdPre,QuickfixCmdPost * \"\naugroup END\n\nfunction! s:ReplaceCmd(cmd) abort\n  let temp = tempname()\n  let [err, exec_error] = s:StdoutToFile(temp, a:cmd)\n  if exec_error\n    throw 'fugitive: ' . (len(err) ? substitute(err, \"\\n$\", '', '') : 'unknown error running ' . string(a:cmd))\n  endif\n  setlocal noswapfile\n  silent exe 'lockmarks keepalt noautocmd 0read ++edit' s:fnameescape(temp)\n  if &foldenable && foldlevel('$') > 0\n    set nofoldenable\n    silent keepjumps $delete _\n    set foldenable\n  else\n    silent keepjumps $delete _\n  endif\n  call delete(temp)\n  if s:cpath(s:AbsoluteVimPath(bufnr('$')), temp)\n    silent! noautocmd execute bufnr('$') . 'bwipeout'\n  endif\nendfunction\n\nfunction! s:FormatLog(dict) abort\n  return a:dict.commit . ' ' . a:dict.subject\nendfunction\n\nfunction! s:FormatRebase(dict) abort\n  return a:dict.status . ' ' . a:dict.commit . ' ' . a:dict.subject\nendfunction\n\nfunction! s:FormatFile(dict) abort\n  return a:dict.status . ' ' . a:dict.filename\nendfunction\n\nfunction! s:Format(val) abort\n  if type(a:val) == type({})\n    return s:Format{a:val.type}(a:val)\n  elseif type(a:val) == type([])\n    return map(copy(a:val), 's:Format(v:val)')\n  else\n    return '' . a:val\n  endif\nendfunction\n\nfunction! s:AddHeader(to, key, value) abort\n  if empty(a:value)\n    return\n  endif\n  call add(a:to.lines, a:key . ':' . (len(a:value) ? ' ' . a:value : ''))\nendfunction\n\nfunction! s:AddSection(to, label, lines, ...) abort\n  let note = a:0 ? a:1 : ''\n  if empty(a:lines) && empty(note)\n    return\n  endif\n  call extend(a:to.lines, ['', a:label . (len(note) ? ': ' . note : ' (' . len(a:lines) . ')')] + s:Format(a:lines))\nendfunction\n\nfunction! s:AddDiffSection(to, stat, label, files) abort\n  if empty(a:files)\n    return\n  endif\n  let diff_section = a:stat.diff[a:label]\n  let expanded = a:stat.expanded[a:label]\n  let was_expanded = get(getbufvar(a:stat.bufnr, 'fugitive_expanded', {}), a:label, {})\n  call extend(a:to.lines, ['', a:label . ' (' . len(a:files) . ')'])\n  for file in a:files\n    call add(a:to.lines, s:Format(file))\n    if has_key(was_expanded, file.filename)\n      let [diff, start] = s:StageInlineGetDiff(diff_section, file)\n      if len(diff)\n        let expanded[file.filename] = [start]\n        call extend(a:to.lines, diff)\n      endif\n    endif\n  endfor\nendfunction\n\nfunction! s:QueryLog(refspec, limit, dir) abort\n  let [log, exec_error] = s:LinesError(['log', '-n', '' . a:limit, '--pretty=format:%h%x09%s'] + a:refspec + ['--'], a:dir)\n  call map(log, 'split(v:val, \"\\t\", 1)')\n  call map(log, '{\"type\": \"Log\", \"commit\": v:val[0], \"subject\": join(v:val[1 : -1], \"\\t\")}')\n  let result = {'error': exec_error ? 1 : 0, 'overflow': 0, 'entries': log}\n  if len(log) == a:limit\n    call remove(log, -1)\n    let result.overflow = 1\n  endif\n  return result\nendfunction\n\nfunction! s:QueryLogRange(old, new, dir) abort\n  if empty(a:old) || empty(a:new)\n    return {'error': 2, 'overflow': 0, 'entries': []}\n  endif\n  return s:QueryLog([a:old . '..' . a:new], 256, a:dir)\nendfunction\n\nfunction! s:AddLogSection(to, label, log) abort\n  if empty(a:log.entries)\n    return\n  endif\n  let label = a:label . ' (' . len(a:log.entries) . (a:log.overflow ? '+' : '') . ')'\n  call extend(a:to.lines, ['', label] + s:Format(a:log.entries))\nendfunction\n\nlet s:rebase_abbrevs = {\n      \\ 'p': 'pick',\n      \\ 'r': 'reword',\n      \\ 'e': 'edit',\n      \\ 's': 'squash',\n      \\ 'f': 'fixup',\n      \\ 'x': 'exec',\n      \\ 'd': 'drop',\n      \\ 'l': 'label',\n      \\ 't': 'reset',\n      \\ 'm': 'merge',\n      \\ 'b': 'break',\n      \\ }\n\nfunction! s:MapStatus() abort\n  call fugitive#MapJumps()\n  call s:Map('n', '-', \":<C-U>execute <SID>Do('Toggle',0)<CR>\", '<silent>')\n  call s:Map('x', '-', \":<C-U>execute <SID>Do('Toggle',1)<CR>\", '<silent>')\n  call s:Map('n', 's', \":<C-U>execute <SID>Do('Stage',0)<CR>\", '<silent>')\n  call s:Map('x', 's', \":<C-U>execute <SID>Do('Stage',1)<CR>\", '<silent>')\n  call s:Map('n', 'u', \":<C-U>execute <SID>Do('Unstage',0)<CR>\", '<silent>')\n  call s:Map('x', 'u', \":<C-U>execute <SID>Do('Unstage',1)<CR>\", '<silent>')\n  call s:Map('n', 'U', \":<C-U>Git reset -q<CR>\", '<silent>')\n  call s:MapMotion('gu', \"exe <SID>StageJump(v:count, 'Untracked', 'Unstaged')\")\n  call s:MapMotion('gU', \"exe <SID>StageJump(v:count, 'Unstaged', 'Untracked')\")\n  call s:MapMotion('gs', \"exe <SID>StageJump(v:count, 'Staged')\")\n  call s:MapMotion('gp', \"exe <SID>StageJump(v:count, 'Unpushed')\")\n  call s:MapMotion('gP', \"exe <SID>StageJump(v:count, 'Unpulled')\")\n  call s:MapMotion('gr', \"exe <SID>StageJump(v:count, 'Rebasing')\")\n  call s:Map('n', 'C', \":echoerr 'fugitive: C has been removed in favor of cc'<CR>\", '<silent><unique>')\n  call s:Map('n', 'a', \":echoerr 'fugitive: a has been removed in favor of s'<CR>\", '<silent><unique>')\n  call s:Map('n', 'i', \":<C-U>execute <SID>NextExpandedHunk(v:count1)<CR>\", '<silent>')\n  call s:Map('n', \"=\", \":<C-U>execute <SID>StageInline('toggle',line('.'),v:count)<CR>\", '<silent>')\n  call s:Map('n', \"<\", \":<C-U>execute <SID>StageInline('hide',  line('.'),v:count)<CR>\", '<silent>')\n  call s:Map('n', \">\", \":<C-U>execute <SID>StageInline('show',  line('.'),v:count)<CR>\", '<silent>')\n  call s:Map('x', \"=\", \":<C-U>execute <SID>StageInline('toggle',line(\\\"'<\\\"),line(\\\"'>\\\")-line(\\\"'<\\\")+1)<CR>\", '<silent>')\n  call s:Map('x', \"<\", \":<C-U>execute <SID>StageInline('hide',  line(\\\"'<\\\"),line(\\\"'>\\\")-line(\\\"'<\\\")+1)<CR>\", '<silent>')\n  call s:Map('x', \">\", \":<C-U>execute <SID>StageInline('show',  line(\\\"'<\\\"),line(\\\"'>\\\")-line(\\\"'<\\\")+1)<CR>\", '<silent>')\n  call s:Map('n', 'D', \":echoerr 'fugitive: D has been removed in favor of dd'<CR>\", '<silent><unique>')\n  call s:Map('n', 'dd', \":<C-U>execute <SID>StageDiff('Gdiffsplit')<CR>\", '<silent>')\n  call s:Map('n', 'dh', \":<C-U>execute <SID>StageDiff('Ghdiffsplit')<CR>\", '<silent>')\n  call s:Map('n', 'ds', \":<C-U>execute <SID>StageDiff('Ghdiffsplit')<CR>\", '<silent>')\n  call s:Map('n', 'dp', \":<C-U>execute <SID>StageDiffEdit()<CR>\", '<silent>')\n  call s:Map('n', 'dv', \":<C-U>execute <SID>StageDiff('Gvdiffsplit')<CR>\", '<silent>')\n  call s:Map('n', 'd?', \":<C-U>help fugitive_d<CR>\", '<silent>')\n  call s:Map('n', 'P', \":<C-U>execute <SID>StagePatch(line('.'),line('.')+v:count1-1)<CR>\", '<silent>')\n  call s:Map('x', 'P', \":<C-U>execute <SID>StagePatch(line(\\\"'<\\\"),line(\\\"'>\\\"))<CR>\", '<silent>')\n  call s:Map('n', 'p', \":<C-U>if v:count<Bar>silent exe <SID>GF('pedit')<Bar>else<Bar>echoerr 'Use = for inline diff, I for :Git add/reset --patch, 1p for :pedit'<Bar>endif<CR>\", '<silent>')\n  call s:Map('x', 'p', \":<C-U>execute <SID>StagePatch(line(\\\"'<\\\"),line(\\\"'>\\\"))<CR>\", '<silent>')\n  call s:Map('n', 'I', \":<C-U>execute <SID>StagePatch(line('.'),line('.'), 1)<CR>\", '<silent>')\n  call s:Map('x', 'I', \":<C-U>execute <SID>StagePatch(line(\\\"'<\\\"),line(\\\"'>\\\"), 1)<CR>\", '<silent>')\n  call s:Map('n', 'gq', \":<C-U>if bufnr('$') == 1<Bar>quit<Bar>else<Bar>bdelete<Bar>endif<CR>\", '<silent>')\n  call s:Map('n', 'R', \":echohl WarningMsg<Bar>echo 'Reloading is automatic.  Use :e to force'<Bar>echohl NONE<CR>\", '<silent>')\n  call s:Map('n', 'g<Bar>', \":<C-U>echoerr 'Changed to X'<CR>\", '<silent><unique>')\n  call s:Map('x', 'g<Bar>', \":<C-U>echoerr 'Changed to X'<CR>\", '<silent><unique>')\n  call s:Map('n', 'X', \":<C-U>execute <SID>StageDelete(line('.'), 0, v:count)<CR>\", '<silent>')\n  call s:Map('x', 'X', \":<C-U>execute <SID>StageDelete(line(\\\"'<\\\"), line(\\\"'>\\\"), v:count)<CR>\", '<silent>')\n  call s:Map('n', 'gI', \":<C-U>execute <SID>StageIgnore(line('.'), line('.'), v:count)<CR>\", '<silent>')\n  call s:Map('x', 'gI', \":<C-U>execute <SID>StageIgnore(line(\\\"'<\\\"), line(\\\"'>\\\"), v:count)<CR>\", '<silent>')\n  call s:Map('n', '.', ':<C-U> <C-R>=<SID>StageArgs(0)<CR><Home>')\n  call s:Map('x', '.', ':<C-U> <C-R>=<SID>StageArgs(1)<CR><Home>')\nendfunction\n\nfunction! s:StatusProcess(result, stat) abort\n  let stat = a:stat\n  let status_exec = a:stat.status\n  let config = a:stat.config\n  let dir = s:Dir(config)\n  try\n    let [staged, unstaged, untracked] = [[], [], []]\n    let stat.props = {}\n\n    if empty(status_exec)\n      let stat.branch = FugitiveHead(0, config)\n\n    elseif status_exec.exit_status\n      let stat.error = s:JoinChomp(status_exec.stderr)\n      return\n\n    elseif status_exec.args[-1] ==# '--porcelain=v2'\n      let output = split(tr(join(status_exec.stdout, \"\\1\"), \"\\1\\n\", \"\\n\\1\"), \"\\1\", 1)[0:-2]\n      let i = 0\n      while i < len(output)\n        let line = output[i]\n        let prop = matchlist(line, '# \\(\\S\\+\\) \\(.*\\)')\n        if len(prop)\n          let stat.props[prop[1]] = prop[2]\n        elseif line[0] ==# '?'\n          call add(untracked, {'type': 'File', 'status': line[0], 'filename': line[2:-1], 'relative': [line[2:-1]]})\n        elseif line[0] !=# '#'\n          if line[0] ==# 'u'\n            let file = matchstr(line, '^.\\{37\\} \\x\\{40,\\} \\x\\{40,\\} \\x\\{40,\\} \\zs.*$')\n          else\n            let file = matchstr(line, '^.\\{30\\} \\x\\{40,\\} \\x\\{40,\\} \\zs.*$')\n          endif\n          if line[0] ==# '2'\n            let i += 1\n            let file = matchstr(file, ' \\zs.*')\n            let relative = [file, output[i]]\n          else\n            let relative = [file]\n          endif\n          let filename = join(reverse(copy(relative)), ' -> ')\n          let sub = matchstr(line, '^[12u] .. \\zs....')\n          if line[2] !=# '.'\n            call add(staged, {'type': 'File', 'status': line[2], 'filename': filename, 'relative': relative, 'submodule': sub})\n          endif\n          if line[3] !=# '.'\n            let sub = matchstr(line, '^[12u] .. \\zs....')\n            call add(unstaged, {'type': 'File', 'status': get({'C':'M','M':'?','U':'?'}, matchstr(sub, 'S\\.*\\zs[CMU]'), line[3]), 'filename': file, 'relative': [file], 'submodule': sub})\n          endif\n        endif\n        let i += 1\n      endwhile\n      let stat.branch = substitute(get(stat.props, 'branch.head', '(unknown)'), '\\C^(\\%(detached\\|unknown\\))$', '', '')\n\n    else\n      let output = split(tr(join(status_exec.stdout, \"\\1\"), \"\\1\\n\", \"\\n\\1\"), \"\\1\", 1)[0:-2]\n      while get(output, 0, '') =~# '^\\l\\+:'\n        call remove(output, 0)\n      endwhile\n      let branch = matchstr(output[0], '^## \\zs\\S\\+\\ze\\%($\\| \\[\\)')\n      if branch =~# '\\.\\.\\.'\n        let stat.branch = split(branch, '\\.\\.\\.')[0]\n      else\n        let stat.branch = branch ==# 'HEAD' ? '' : branch\n      endif\n\n      let i = 0\n      while i < len(output)\n        let line = output[i]\n        let file = line[3:-1]\n        let i += 1\n        if line[2] !=# ' '\n          continue\n        endif\n        if line[0:1] =~# '[RC]'\n          let relative = [file, output[i]]\n          let i += 1\n        else\n          let relative = [file]\n        endif\n        let filename = join(reverse(copy(relative)), ' -> ')\n        if line[0] !~# '[ ?!#]'\n          call add(staged, {'type': 'File', 'status': line[0], 'filename': filename, 'relative': relative, 'submodule': ''})\n        endif\n        if line[0:1] ==# '??'\n          call add(untracked, {'type': 'File', 'status': line[1], 'filename': filename, 'relative': relative})\n        elseif line[1] !~# '[ !#]'\n          call add(unstaged, {'type': 'File', 'status': line[1], 'filename': file, 'relative': [file], 'submodule': ''})\n        endif\n      endwhile\n    endif\n\n    let diff_cmd = stat.cmd + ['-c', 'diff.suppressBlankEmpty=false', '-c', 'core.quotePath=false', 'diff', '--color=never', '--no-ext-diff', '--no-prefix']\n    let stat.diff = {'Staged': {'stdout': ['']}, 'Unstaged': {'stdout': ['']}}\n    if len(staged)\n      let stat.diff['Staged'] = fugitive#Execute(diff_cmd + ['--cached'], function('len'))\n    endif\n    if len(unstaged)\n      let stat.diff['Unstaged'] = fugitive#Execute(diff_cmd + ['--'] + map(copy(unstaged), 'stat.work_tree . \"/\" . v:val.relative[0]'), function('len'))\n    endif\n\n    let [stat.staged, stat.unstaged, stat.untracked] = [staged, unstaged, untracked]\n\n    let stat.files = {'Staged': {}, 'Unstaged': {}}\n    for dict in staged\n      let stat.files['Staged'][dict.filename] = dict\n    endfor\n    for dict in unstaged\n      let stat.files['Unstaged'][dict.filename] = dict\n    endfor\n\n    let branch = stat.branch\n    let fetch_remote = config.Get('branch.' . branch . '.remote', 'origin')\n    let push_remote = config.Get('branch.' . branch . '.pushRemote',\n          \\ config.Get('remote.pushDefault', fetch_remote))\n    if fetch_remote !=# '.' && empty(config.Get('remote.' . fetch_remote . '.fetch'))\n      let fetch_remote = ''\n    endif\n    if push_remote !=# '.' && empty(config.Get('remote.' . push_remote . '.push', config.Get('remote.' . push_remote . '.fetch')))\n      let push_remote = ''\n    endif\n    let stat.fetch_remote = fetch_remote\n    let stat.push_remote = push_remote\n\n    if empty(stat.fetch_remote) || empty(branch)\n      let stat.merge = ''\n    else\n      let stat.merge = config.Get('branch.' . branch . '.merge')\n    endif\n\n    let push_default = FugitiveConfigGet('push.default', config)\n    if empty(push_default)\n      let push_default = fugitive#GitVersion(2) ? 'simple' : 'matching'\n    endif\n    if push_default ==# 'upstream'\n      let stat.push = stat.merge\n    elseif empty(stat.push_remote) || empty(branch)\n      let stat.push = ''\n    else\n      let stat.push = 'refs/heads/' . branch\n    endif\n\n    let stat.pull_type = 'Pull'\n    if len(stat.merge)\n      let rebase = FugitiveConfigGet('branch.' . branch . '.rebase', config)\n      if empty(rebase)\n        let rebase = FugitiveConfigGet('pull.rebase', config)\n      endif\n      if rebase =~# '^\\%(true\\|yes\\|on\\|1\\|interactive\\|merges\\|preserve\\)$'\n        let stat.pull_type = 'Rebase'\n      elseif rebase =~# '^\\%(false\\|no|off\\|0\\|\\)$'\n        let stat.pull_type = 'Merge'\n      endif\n    endif\n  endtry\nendfunction\n\nfunction! s:StatusRender(stat) abort\n  try\n    let stat = a:stat\n    call fugitive#Wait(stat.running)\n    if has_key(stat, 'error')\n      return 'echoerr ' . string('fugitive: ' . stat.error)\n    endif\n    let [staged, unstaged, untracked, config] = [stat.staged, stat.unstaged, stat.untracked, stat.config]\n    let dir = s:Dir(config)\n\n    let pull_ref = stat.merge\n    if stat.fetch_remote !=# '.'\n      let pull_ref = substitute(pull_ref, '^refs/heads/', 'refs/remotes/' . stat.fetch_remote . '/', '')\n    endif\n\n    let push_ref = stat.push\n    if stat.push_remote !=# '.'\n      let push_ref = substitute(push_ref, '^refs/heads/', 'refs/remotes/' . stat.push_remote . '/', '')\n    endif\n\n    let push_short = substitute(push_ref, '^refs/\\w\\+/', '', '')\n    let pull_short = substitute(pull_ref, '^refs/\\w\\+/', '', '')\n\n    if isdirectory(fugitive#Find('.git/rebase-merge/', dir))\n      let rebasing_dir = fugitive#Find('.git/rebase-merge/', dir)\n    elseif isdirectory(fugitive#Find('.git/rebase-apply/', dir))\n      let rebasing_dir = fugitive#Find('.git/rebase-apply/', dir)\n    endif\n\n    call fugitive#Wait(stat.rev_parse)\n    let head = empty(stat.branch) ? stat.rev_parse.stdout[0] : stat.branch\n\n    let rebasing = []\n    let rebasing_head = 'detached HEAD'\n    if exists('rebasing_dir') && filereadable(rebasing_dir . 'git-rebase-todo')\n      let rebasing_head = substitute(readfile(rebasing_dir . 'head-name')[0], '\\C^refs/heads/', '', '')\n      let len = len(stat.rev_parse.stdout[0])\n      let lines = readfile(rebasing_dir . 'git-rebase-todo')\n      if getfsize(rebasing_dir . 'done') > 0\n        let done = readfile(rebasing_dir . 'done')\n        call map(done, 'substitute(v:val, ''^\\l\\+\\>'', \"done\", \"\")')\n        let done[-1] = substitute(done[-1], '^\\l\\+\\>', 'stop', '')\n        let lines = done + lines\n      endif\n      call reverse(lines)\n      for line in lines\n        let match = matchlist(line, '^\\(\\l\\+\\)\\s\\+\\(\\x\\{4,\\}\\)\\s\\+\\(.*\\)')\n        if len(match) && match[1] !~# 'exec\\|merge\\|label'\n          call add(rebasing, {'type': 'Rebase', 'status': get(s:rebase_abbrevs, match[1], match[1]), 'commit': strpart(match[2], 0, len), 'subject': match[3]})\n        endif\n      endfor\n    endif\n\n    let sequencing = []\n    try\n      let sequencer_todo = reverse(readfile(fugitive#Find('.git/sequencer/todo', dir)))\n    catch\n    endtry\n    if exists('sequencer_todo')\n      for line in sequencer_todo\n        let match = matchlist(line, '^\\(\\l\\+\\)\\s\\+\\(\\x\\{4,\\}\\)\\s\\+\\(.*\\)')\n        if len(match) && match[1] !~# 'exec\\|merge\\|label'\n          call add(sequencing, {'type': 'Rebase', 'status': get(s:rebase_abbrevs, match[1], match[1]), 'commit': match[2], 'subject': match[3]})\n        endif\n      endfor\n    else\n      try\n        let merge_msg = get(readfile(fugitive#Find('.git/MERGE_MSG', dir), '', 1), 0, '')\n      catch\n      endtry\n    endif\n    if exists('merge_msg')\n      if filereadable(fugitive#Find('.git/CHERRY_PICK_HEAD', dir))\n        let pick_head = fugitive#Execute(['rev-parse', '--short', 'CHERRY_PICK_HEAD', '--'], dir).stdout[0]\n        if !empty(pick_head)\n          call add(sequencing, {'type': 'Rebase', 'status': 'pick', 'commit': pick_head, 'subject': merge_msg})\n        endif\n      elseif filereadable(fugitive#Find('.git/REVERT_HEAD', dir))\n        let pick_head = fugitive#Execute(['rev-parse', '--short', 'REVERT_HEAD', '--'], dir).stdout[0]\n        if !empty(pick_head)\n          call add(sequencing, {'type': 'Rebase', 'status': 'revert', 'commit': pick_head, 'subject': merge_msg})\n        endif\n      endif\n    endif\n\n    let stat.expanded = {'Staged': {}, 'Unstaged': {}}\n    let to = {'lines': []}\n    call s:AddHeader(to, 'Head', head)\n    call s:AddHeader(to, stat.pull_type, pull_short)\n    if push_ref !=# pull_ref\n      call s:AddHeader(to, 'Push', push_short)\n    endif\n    if empty(stat.work_tree)\n      if get(fugitive#ConfigGetAll('core.bare', config), 0, '') !~# '^\\%(false\\|no|off\\|0\\|\\)$'\n        call s:AddHeader(to, 'Bare', 'yes')\n      else\n        call s:AddHeader(to, 'Error', s:worktree_error)\n      endif\n    endif\n    if get(fugitive#ConfigGetAll('advice.statusHints', config), 0, 'true') !~# '^\\%(false\\|no|off\\|0\\|\\)$'\n      call s:AddHeader(to, 'Help', 'g?')\n    endif\n\n    call s:AddSection(to, 'Rebasing ' . rebasing_head, rebasing)\n    call s:AddSection(to, get(get(sequencing, 0, {}), 'status', '') ==# 'revert' ? 'Reverting' : 'Cherry Picking', sequencing)\n    call s:AddSection(to, 'Untracked', untracked)\n    call s:AddDiffSection(to, stat, 'Unstaged', unstaged)\n    call s:AddDiffSection(to, stat, 'Staged', staged)\n\n    let unique_push_ref = push_ref ==# pull_ref ? '' : push_ref\n    let unpushed_push = s:QueryLogRange(unique_push_ref, head, dir)\n    if get(stat.props, 'branch.ab') =~# '^+0 '\n      let unpushed_pull = {'error': 0, 'overflow': 0, 'entries': []}\n    else\n      let unpushed_pull = s:QueryLogRange(pull_ref, head, dir)\n    endif\n    \" If the push ref is defined but nowhere to be found at the remote,\n    \" pretend it's the same as the pull ref\n    if unpushed_push.error == 1\n      let unpushed_push = unpushed_pull\n    endif\n    call s:AddLogSection(to, 'Unpushed to ' . push_short, unpushed_push)\n    call s:AddLogSection(to, 'Unpushed to ' . pull_short, unpushed_pull)\n    if unpushed_push.error && unpushed_pull.error && empty(rebasing) &&\n          \\ !empty(stat.push_remote . stat.fetch_remote)\n      call s:AddLogSection(to, 'Unpushed to *', s:QueryLog([head, '--not', '--remotes'], 256, dir))\n    endif\n    call s:AddLogSection(to, 'Unpulled from ' . push_short, s:QueryLogRange(head, unique_push_ref, dir))\n    if len(pull_ref) && get(stat.props, 'branch.ab') !~# ' -0$'\n      call s:AddLogSection(to, 'Unpulled from ' . pull_short, s:QueryLogRange(head, pull_ref, dir))\n    endif\n\n    let bufnr = stat.bufnr\n    setlocal noreadonly modifiable\n    if len(to.lines) < line('$')\n      silent keepjumps execute (len(to.lines)+1) . ',$delete_'\n    endif\n    call setline(1, to.lines)\n    call setbufvar(bufnr, 'fugitive_status', stat)\n    call setbufvar(bufnr, 'fugitive_expanded', stat.expanded)\n    setlocal nomodified readonly nomodifiable\n    return ''\n  finally\n    let b:fugitive_type = 'index'\n  endtry\nendfunction\n\nfunction! s:StatusRetrieve(bufnr, ...) abort\n  let amatch = s:Slash(fnamemodify(bufname(a:bufnr), ':p'))\n  let dir = s:Dir(a:bufnr)\n  let config = fugitive#Config(dir, function('len'))\n\n  let cmd = [dir]\n  if amatch !~# '^fugitive:' && s:cpath($GIT_INDEX_FILE !=# '' ? resolve(s:GitIndexFileEnv()) : fugitive#Find('.git/index', dir)) !=# s:cpath(amatch)\n    let cmd += [{'env': {'GIT_INDEX_FILE': FugitiveGitPath(amatch)}}]\n  endif\n\n  if fugitive#GitVersion(2, 15)\n    call add(cmd, '--no-optional-locks')\n  endif\n\n  let rev_parse_cmd = cmd + ['rev-parse', '--short', 'HEAD', '--']\n\n  let stat = {'bufnr': a:bufnr, 'reltime': reltime(), 'work_tree': s:Tree(dir), 'cmd': cmd, 'config': config}\n  if empty(stat.work_tree)\n    let stat.rev_parse = call('fugitive#Execute', [rev_parse_cmd, function('s:StatusProcess'), stat] + a:000)\n    let stat.status = {}\n    let stat.running = stat.rev_parse\n  else\n    let stat.rev_parse = fugitive#Execute(rev_parse_cmd)\n    let status_cmd = cmd + ['status', '-bz', fugitive#GitVersion(2, 11) ? '--porcelain=v2' : '--porcelain']\n    let stat.status = call('fugitive#Execute', [status_cmd, function('s:StatusProcess'), stat] + a:000)\n    let stat.running = stat.status\n  endif\n  return stat\nendfunction\n\nfunction! fugitive#BufReadStatus(cmdbang) abort\n  exe s:VersionCheck()\n  if a:cmdbang\n    unlet! b:fugitive_expanded\n  endif\n  let b:fugitive_type = 'index'\n  let stat = s:StatusRetrieve(bufnr(''))\n  try\n    let b:fugitive_loading = stat\n    doautocmd <nomodeline> BufReadPre\n\n    setlocal readonly nomodifiable noswapfile nomodeline buftype=nowrite\n    call s:MapStatus()\n\n    call s:StatusRender(stat)\n\n    doautocmd <nomodeline> BufReadPost\n    if &bufhidden ==# ''\n      setlocal bufhidden=delete\n    endif\n    if !exists('b:dispatch')\n      let b:dispatch = ':Git fetch --all'\n    endif\n    setlocal filetype=fugitive\n\n    return s:DoAutocmd('User FugitiveIndex')\n  finally\n    call setbufvar(stat.bufnr, 'fugitive_loading', {})\n  endtry\nendfunction\n\nfunction! fugitive#FileReadCmd(...) abort\n  let amatch = a:0 ? a:1 : expand('<amatch>')\n  let [dir, rev] = s:DirRev(amatch)\n  let line = a:0 > 1 ? a:2 : line(\"'[\")\n  if empty(dir)\n    return 'noautocmd ' . line . 'read ' . s:fnameescape(amatch)\n  endif\n  if rev !~# ':' && s:ChompDefault('', [dir, 'cat-file', '-t', rev]) =~# '^\\%(commit\\|tag\\)$'\n    let cmd = [dir, 'log', '--pretty=format:%B', '-1', rev, '--']\n  elseif rev ==# ':'\n    let cmd = [dir, 'status', '--short']\n  else\n    let cmd = [dir, 'cat-file', '-p', rev, '--']\n  endif\n  let temp = tempname()\n  let [err, exec_error] = s:StdoutToFile(temp, cmd)\n  if exec_error\n    call delete(temp)\n    return 'noautocmd ' . line . 'read ' . s:fnameescape(amatch)\n  else\n    return 'silent keepalt ' . line . 'read ' . s:fnameescape(temp) . '|call delete(' . string(temp) . ')'\n  endif\nendfunction\n\nfunction! fugitive#FileWriteCmd(...) abort\n  let temp = tempname()\n  let amatch = a:0 ? a:1 : expand('<amatch>')\n  let autype = a:0 > 1 ? 'Buf' : 'File'\n  if exists('#' . autype . 'WritePre')\n    execute s:DoAutocmd(autype . 'WritePre ' . s:fnameescape(amatch))\n  endif\n  try\n    let [dir, commit, file] = s:DirCommitFile(amatch)\n    if commit !~# '^[0-3]$' || !v:cmdbang && (line(\"'[\") != 1 || line(\"']\") != line('$'))\n      return \"noautocmd '[,']write\" . (v:cmdbang ? '!' : '') . ' ' . s:fnameescape(amatch)\n    endif\n    silent execute \"noautocmd keepalt '[,']write \".temp\n    let hash = s:TreeChomp([dir, '--literal-pathspecs', 'hash-object', '-w', '--', FugitiveGitPath(temp)])\n    let old_mode = matchstr(s:ChompDefault('', ['ls-files', '--stage', '.' . file], dir), '^\\d\\+')\n    if empty(old_mode)\n      let old_mode = executable(s:Tree(dir) . file) ? '100755' : '100644'\n    endif\n    let error = s:UpdateIndex(dir, [old_mode, hash, commit, file[1:-1]])\n    if empty(error)\n      setlocal nomodified\n      if exists('#' . autype . 'WritePost')\n        execute s:DoAutocmd(autype . 'WritePost ' . s:fnameescape(amatch))\n      endif\n      exe s:DoAutocmdChanged(dir)\n      return ''\n    else\n      return 'echoerr '.string('fugitive: '.error)\n    endif\n  catch /^fugitive:/\n    return 'echoerr ' . string(v:exception)\n  finally\n    call delete(temp)\n  endtry\nendfunction\n\nfunction! fugitive#BufReadCmd(...) abort\n  let amatch = a:0 ? a:1 : expand('<amatch>')\n  let [dir, rev] = s:DirRev(amatch)\n  if empty(dir)\n    return 'echo \"Invalid Fugitive URL\"'\n  endif\n  call s:InitializeBuffer(dir)\n  if rev ==# ':'\n    return fugitive#BufReadStatus(v:cmdbang)\n  endif\n  try\n    if rev =~# '^:\\d$'\n      let b:fugitive_type = 'stage'\n    else\n      let r = fugitive#Execute([dir, 'cat-file', '-t', rev])\n      let b:fugitive_type = get(r.stdout, 0, '')\n      if r.exit_status && rev =~# '^:0'\n        let r = fugitive#Execute([dir, 'write-tree', '--prefix=' . rev[3:-1]])\n        let sha = get(r.stdout, 0, '')\n        let b:fugitive_type = 'tree'\n      endif\n      if r.exit_status\n        let error = substitute(join(r.stderr, \"\\n\"), \"\\n*$\", '', '')\n        unlet b:fugitive_type\n        setlocal noswapfile\n        if empty(&bufhidden)\n          setlocal bufhidden=delete\n        endif\n        if rev =~# '^:\\d:'\n          let &l:readonly = !filewritable(fugitive#Find('.git/index', dir))\n          return 'doautocmd BufNewFile'\n        else\n          setlocal readonly nomodifiable\n          return 'doautocmd BufNewFile|echo ' . string(error)\n        endif\n      elseif b:fugitive_type !~# '^\\%(tag\\|commit\\|tree\\|blob\\)$'\n        return \"echoerr \".string(\"fugitive: unrecognized git type '\".b:fugitive_type.\"'\")\n      endif\n      if !exists('b:fugitive_display_format') && b:fugitive_type != 'blob'\n        let b:fugitive_display_format = +getbufvar('#','fugitive_display_format')\n      endif\n    endif\n\n    if b:fugitive_type !=# 'blob'\n      setlocal nomodeline\n    endif\n\n    setlocal noreadonly modifiable\n    let pos = getpos('.')\n    silent keepjumps %delete_\n    setlocal endofline\n\n    let events = ['User FugitiveObject', 'User Fugitive' . substitute(b:fugitive_type, '^\\l', '\\u&', '')]\n\n    try\n      if b:fugitive_type !=# 'blob'\n        setlocal foldmarker=<<<<<<<<,>>>>>>>>\n      endif\n      exe s:DoAutocmd('BufReadPre')\n      if b:fugitive_type ==# 'tree'\n        let b:fugitive_display_format = b:fugitive_display_format % 2\n        if b:fugitive_display_format\n          call s:ReplaceCmd([dir, 'ls-tree', exists('sha') ? sha : rev])\n        else\n          if !exists('sha')\n            let sha = s:TreeChomp(dir, 'rev-parse', '--verify', rev, '--')\n          endif\n          call s:ReplaceCmd([dir, 'show', '--no-color', sha])\n        endif\n      elseif b:fugitive_type ==# 'tag'\n        let b:fugitive_display_format = b:fugitive_display_format % 2\n        if b:fugitive_display_format\n          call s:ReplaceCmd([dir, 'cat-file', b:fugitive_type, rev])\n        else\n          call s:ReplaceCmd([dir, 'cat-file', '-p', rev])\n        endif\n      elseif b:fugitive_type ==# 'commit'\n        let b:fugitive_display_format = b:fugitive_display_format % 2\n        if b:fugitive_display_format\n          call s:ReplaceCmd([dir, 'cat-file', b:fugitive_type, rev])\n        else\n          call s:ReplaceCmd([dir, '-c', 'diff.noprefix=false', '-c', 'log.showRoot=false', 'show', '--no-color', '-m', '--first-parent', '--pretty=format:tree%x20%T%nparent%x20%P%nauthor%x20%an%x20<%ae>%x20%ad%ncommitter%x20%cn%x20<%ce>%x20%cd%nencoding%x20%e%n%n%B', rev])\n          keepjumps 1\n          keepjumps call search('^parent ')\n          if getline('.') ==# 'parent '\n            silent lockmarks keepjumps delete_\n          else\n            silent exe (exists(':keeppatterns') ? 'keeppatterns' : '') 'keepjumps s/\\m\\C\\%(^parent\\)\\@<! /\\rparent /e' . (&gdefault ? '' : 'g')\n          endif\n          keepjumps let lnum = search('^encoding \\%(<unknown>\\)\\=$','W',line('.')+3)\n          if lnum\n            silent lockmarks keepjumps delete_\n          end\n          silent exe (exists(':keeppatterns') ? 'keeppatterns' : '') 'keepjumps 1,/^diff --git\\|\\%$/s/\\r$//e'\n          keepjumps 1\n        endif\n      elseif b:fugitive_type ==# 'stage'\n        call s:ReplaceCmd([dir, 'ls-files', '--stage'])\n      elseif b:fugitive_type ==# 'blob'\n        let blob_or_filters = rev =~# ':' && fugitive#GitVersion(2, 11) ? '--filters' : 'blob'\n        call s:ReplaceCmd([dir, 'cat-file', blob_or_filters, rev])\n      endif\n    finally\n      keepjumps call setpos('.',pos)\n      setlocal nomodified noswapfile\n      let modifiable = rev =~# '^:.:' && b:fugitive_type !=# 'tree'\n      if modifiable\n        let events = ['User FugitiveStageBlob']\n      endif\n      let &l:readonly = !modifiable || !filewritable(fugitive#Find('.git/index', dir))\n      if empty(&bufhidden)\n        setlocal bufhidden=delete\n      endif\n      let &l:modifiable = modifiable\n      call fugitive#MapJumps()\n      if b:fugitive_type !=# 'blob'\n        call s:Map('n', 'a', \":<C-U>let b:fugitive_display_format += v:count1<Bar>exe fugitive#BufReadCmd(@%)<CR>\", '<silent>')\n        call s:Map('n', 'i', \":<C-U>let b:fugitive_display_format -= v:count1<Bar>exe fugitive#BufReadCmd(@%)<CR>\", '<silent>')\n        setlocal filetype=git\n      endif\n    endtry\n\n    setlocal modifiable\n\n    return s:DoAutocmd('BufReadPost') .\n          \\ (modifiable ? '' : '|setl nomodifiable') . '|' .\n          \\ call('s:DoAutocmd', events)\n  catch /^fugitive:/\n    return 'echoerr ' . string(v:exception)\n  endtry\nendfunction\n\nfunction! fugitive#BufWriteCmd(...) abort\n  return fugitive#FileWriteCmd(a:0 ? a:1 : expand('<amatch>'), 1)\nendfunction\n\nfunction! fugitive#SourceCmd(...) abort\n  let amatch = a:0 ? a:1 : expand('<amatch>')\n  let temp = s:BlobTemp(amatch)\n  if empty(temp)\n    return 'noautocmd source ' . s:fnameescape(amatch)\n  endif\n  if !exists('g:virtual_scriptnames')\n    let g:virtual_scriptnames = {}\n  endif\n  let g:virtual_scriptnames[temp] = amatch\n  return 'source ' . s:fnameescape(temp)\nendfunction\n\n\" Section: Temp files\n\nif !exists('s:temp_files')\n  let s:temp_files = {}\nendif\n\nfunction! s:TempState(...) abort\n  return get(s:temp_files, s:cpath(s:AbsoluteVimPath(a:0 ? a:1 : -1)), {})\nendfunction\n\nfunction! fugitive#Result(...) abort\n  if !a:0 && exists('g:fugitive_event')\n    return get(g:, 'fugitive_result', {})\n  elseif !a:0 || type(a:1) == type('') && a:1 =~# '^-\\=$'\n    return get(g:, '_fugitive_last_job', {})\n  elseif type(a:1) == type(0)\n    return s:TempState(a:1)\n  elseif type(a:1) == type('')\n    return s:TempState(a:1)\n  elseif type(a:1) == type({}) && has_key(a:1, 'file')\n    return s:TempState(a:1.file)\n  else\n    return {}\n  endif\nendfunction\n\nfunction! s:TempDotMap() abort\n  let cfile = s:cfile()\n  if empty(cfile)\n    if getline('.') =~# '^[*+] \\+\\f' && col('.') < 2\n      return matchstr(getline('.'), '^. \\+\\zs\\f\\+')\n    else\n      return expand('<cfile>')\n    endif\n  endif\n  let name = fugitive#Find(cfile[0])\n  let [dir, commit, file] = s:DirCommitFile(name)\n  if len(commit) && empty(file)\n    return commit\n  elseif s:cpath(s:Tree(), getcwd())\n    return fugitive#Path(name, \"./\")\n  else\n    return fugitive#Real(name)\n  endif\nendfunction\n\nfunction! s:TempReadPre(file) abort\n  let key = s:cpath(s:AbsoluteVimPath(a:file))\n  if has_key(s:temp_files, key)\n    let dict = s:temp_files[key]\n    setlocal nomodeline\n    if empty(&bufhidden)\n      setlocal bufhidden=delete\n    endif\n    setlocal buftype=nowrite\n    setlocal nomodifiable\n    call s:InitializeBuffer(dict)\n    if len(dict.git_dir)\n      call extend(b:, {'fugitive_type': 'temp'}, 'keep')\n    endif\n  endif\n  return ''\nendfunction\n\nfunction! s:TempReadPost(file) abort\n  let key = s:cpath(s:AbsoluteVimPath(a:file))\n  if has_key(s:temp_files, key)\n    let dict = s:temp_files[key]\n    if !has_key(dict, 'job')\n      setlocal nobuflisted\n    endif\n    if get(dict, 'filetype', '') ==# 'git'\n      call fugitive#MapJumps()\n      call s:Map('n', '.', \":<C-U> <C-R>=<SID>fnameescape(<SID>TempDotMap())<CR><Home>\")\n      call s:Map('x', '.', \":<C-U> <C-R>=<SID>fnameescape(<SID>TempDotMap())<CR><Home>\")\n    endif\n    if has_key(dict, 'filetype')\n      if dict.filetype ==# 'man' && has('nvim')\n        let b:man_sect = matchstr(getline(1), '^\\w\\+(\\zs\\d\\+\\ze)')\n      endif\n      if !get(g:, 'did_load_ftplugin') && dict.filetype ==# 'fugitiveblame'\n        call s:BlameMaps(0)\n      endif\n      let &l:filetype = dict.filetype\n    endif\n    setlocal foldmarker=<<<<<<<<,>>>>>>>>\n    if !&modifiable\n      call s:Map('n', 'gq', \":<C-U>bdelete<CR>\", '<silent> <unique>')\n    endif\n    return 'doautocmd <nomodeline> User FugitivePager'\n  endif\n  return ''\nendfunction\n\nfunction! s:TempDelete(file) abort\n  let key = s:cpath(s:AbsoluteVimPath(a:file))\n  if has_key(s:temp_files, key) && !has_key(s:temp_files[key], 'job') && key !=# s:cpath(get(get(g:, '_fugitive_last_job', {}), 'file', ''))\n    call delete(a:file)\n    call remove(s:temp_files, key)\n  endif\n  return ''\nendfunction\n\nfunction! s:OriginBufnr(...) abort\n  let state = s:TempState(a:0 ? a:1 : bufnr(''))\n  return get(state, 'origin_bufnr', -1)\nendfunction\n\naugroup fugitive_temp\n  autocmd!\n  autocmd BufReadPre  * exe s:TempReadPre( +expand('<abuf>'))\n  autocmd BufReadPost * exe s:TempReadPost(+expand('<abuf>'))\n  autocmd BufWipeout  * exe s:TempDelete(  +expand('<abuf>'))\naugroup END\n\n\" Section: :Git\n\nfunction! s:AskPassArgs(dir) abort\n  if (len($DISPLAY) || len($TERM_PROGRAM) || has('gui_running')) &&\n        \\ empty($GIT_ASKPASS) && empty($SSH_ASKPASS) && empty(fugitive#ConfigGetAll('core.askpass', a:dir))\n    if s:executable(s:VimExecPath() . '/git-gui--askpass')\n      return ['-c', 'core.askPass=' . s:ExecPath()[0] . '/git-gui--askpass']\n    elseif s:executable('ssh-askpass')\n      return ['-c', 'core.askPass=ssh-askpass']\n    endif\n  endif\n  return []\nendfunction\n\nfunction! s:RunSave(state) abort\n  let s:temp_files[s:cpath(a:state.file)] = a:state\nendfunction\n\nfunction! s:RunFinished(state, ...) abort\n  if has_key(get(g:, '_fugitive_last_job', {}), 'file') && bufnr(g:_fugitive_last_job.file) < 0\n    exe s:TempDelete(remove(g:, '_fugitive_last_job').file)\n  endif\n  let g:_fugitive_last_job = a:state\n  let first = join(readfile(a:state.file, '', 2), \"\\n\")\n  if get(a:state, 'filetype', '') ==# 'git' && first =~# '\\<\\([[:upper:][:digit:]_-]\\+(\\d\\+)\\).*\\1'\n    let a:state.filetype = 'man'\n  endif\n  if !has_key(a:state, 'capture_bufnr')\n    return\n  endif\n  call fugitive#DidChange(a:state)\nendfunction\n\nfunction! s:RunEdit(state, tmp, job) abort\n  if get(a:state, 'request', '') !=# 'edit'\n    return 0\n  endif\n  call remove(a:state, 'request')\n  let sentinel = a:state.file . '.edit'\n  let file = FugitiveVimPath(readfile(sentinel, '', 1)[0])\n  try\n    if !&equalalways && a:state.mods !~# '\\<\\d*tab\\>' && 3 > (a:state.mods =~# '\\<vert' ? winwidth(0) : winheight(0))\n      let noequalalways = 1\n      setglobal equalalways\n    endif\n    let mods = s:Mods(a:state.mods, 'SpanOrigin')\n    exe substitute(mods, '\\<tab\\>', '-tab', 'g') 'keepalt split' s:fnameescape(file)\n  finally\n    if exists('l:noequalalways')\n      setglobal noequalalways\n    endif\n  endtry\n  set bufhidden=wipe\n  call s:InitializeBuffer(a:state)\n  let bufnr = bufnr('')\n  let s:edit_jobs[bufnr] = [a:state, a:tmp, a:job, sentinel]\n  call fugitive#DidChange(a:state.git_dir)\n  if bufnr == bufnr('') && !exists('g:fugitive_event')\n    try\n      let g:fugitive_event = a:state.git_dir\n      let g:fugitive_result = a:state\n      exe s:DoAutocmd('User FugitiveEditor')\n    finally\n      unlet! g:fugitive_event g:fugitive_result\n    endtry\n  endif\n  return 1\nendfunction\n\nfunction! s:RunReceive(state, tmp, type, job, data, ...) abort\n  if a:type ==# 'err' || a:state.pty\n    let data = type(a:data) == type([]) ? join(a:data, \"\\n\") : a:data\n    let data = a:tmp.escape . data\n    let escape = \"\\033]51;[^\\007]*\"\n    let a:tmp.escape = matchstr(data, escape . '$')\n    if len(a:tmp.escape)\n      let data = strpart(data, 0, len(data) - len(a:tmp.escape))\n    endif\n    let cmd = matchstr(data, escape . \"\\007\")[5:-2]\n    let data = substitute(data, escape . \"\\007\", '', 'g')\n    if cmd =~# '^fugitive:'\n      let a:state.request = strpart(cmd, 9)\n    endif\n    let lines = split(a:tmp.err . data, \"\\r\\\\=\\n\", 1)\n    let a:tmp.err = lines[-1]\n    let lines[-1] = ''\n    call map(lines, 'substitute(v:val, \".*\\r\", \"\", \"\")')\n  else\n    let lines = type(a:data) == type([]) ? a:data : split(a:data, \"\\n\", 1)\n    if len(a:tmp.out)\n      let lines[0] = a:tmp.out . lines[0]\n    endif\n    let a:tmp.out = lines[-1]\n    let lines[-1] = ''\n  endif\n  call writefile(lines, a:state.file, 'ba')\n  if has_key(a:tmp, 'echo')\n    if !exists('l:data')\n      let data = type(a:data) == type([]) ? join(a:data, \"\\n\") : a:data\n    endif\n    let a:tmp.echo .= data\n  endif\n  let line_count = a:tmp.line_count\n  let a:tmp.line_count += len(lines) - 1\n  if !has_key(a:state, 'capture_bufnr') || !bufloaded(a:state.capture_bufnr)\n    return\n  endif\n  call remove(lines, -1)\n  try\n    call setbufvar(a:state.capture_bufnr, '&modifiable', 1)\n    if !line_count && len(lines) > 1000\n      let first = remove(lines, 0, 999)\n      call setbufline(a:state.capture_bufnr, 1, first)\n      redraw\n      call setbufline(a:state.capture_bufnr, 1001, lines)\n    else\n      call setbufline(a:state.capture_bufnr, line_count + 1, lines)\n    endif\n    call setbufvar(a:state.capture_bufnr, '&modifiable', 0)\n    if !a:state.pager && getwinvar(bufwinid(a:state.capture_bufnr), '&previewwindow')\n      let winnr = bufwinnr(a:state.capture_bufnr)\n      if winnr > 0\n        let old_winnr = winnr()\n        exe 'noautocmd' winnr.'wincmd w'\n        $\n        exe 'noautocmd' old_winnr.'wincmd w'\n      endif\n    endif\n  catch\n  endtry\nendfunction\n\nfunction! s:RunExit(state, tmp, job, exit_status) abort\n  let a:state.exit_status = a:exit_status\n  if has_key(a:state, 'job')\n    return\n  endif\n  call s:RunFinished(a:state)\nendfunction\n\nfunction! s:RunClose(state, tmp, job, ...) abort\n  if a:0\n    call s:RunExit(a:state, a:tmp, a:job, a:1)\n  endif\n  let noeol = substitute(substitute(a:tmp.err, \"\\r$\", '', ''), \".*\\r\", '', '') . a:tmp.out\n  call writefile([noeol], a:state.file, 'ba')\n  call remove(a:state, 'job')\n  if has_key(a:state, 'capture_bufnr') && bufloaded(a:state.capture_bufnr)\n    if len(noeol)\n      call setbufvar(a:state.capture_bufnr, '&modifiable', 1)\n      call setbufline(a:state.capture_bufnr, a:tmp.line_count + 1, [noeol])\n      call setbufvar(a:state.capture_bufnr, '&eol', 0)\n      call setbufvar(a:state.capture_bufnr, '&modifiable', 0)\n    endif\n    call setbufvar(a:state.capture_bufnr, '&modified', 0)\n    call setbufvar(a:state.capture_bufnr, '&buflisted', 0)\n    if a:state.filetype !=# getbufvar(a:state.capture_bufnr, '&filetype', '')\n      call setbufvar(a:state.capture_bufnr, '&filetype', a:state.filetype)\n    endif\n  endif\n  if !has_key(a:state, 'exit_status')\n    return\n  endif\n  call s:RunFinished(a:state)\nendfunction\n\nfunction! s:RunSend(job, str) abort\n  try\n    if type(a:job) == type(0)\n      call chansend(a:job, a:str)\n    else\n      call ch_sendraw(a:job, a:str)\n    endif\n    return len(a:str)\n  catch /^Vim\\%((\\a\\+)\\)\\=:E90[06]:/\n    return 0\n  endtry\nendfunction\n\nfunction! s:RunCloseIn(job) abort\n  try\n    if type(a:job) ==# type(0)\n      call chanclose(a:job, 'stdin')\n    else\n      call ch_close_in(a:job)\n    endif\n    return 1\n  catch /^Vim\\%((\\a\\+)\\)\\=:E90[06]:/\n    return 0\n  endtry\nendfunction\n\nfunction! s:RunEcho(tmp) abort\n  if !has_key(a:tmp, 'echo')\n    return\n  endif\n  let data = a:tmp.echo\n  let a:tmp.echo = matchstr(data, \"[\\r\\n]\\\\+$\")\n  if len(a:tmp.echo)\n    let data = strpart(data, 0, len(data) - len(a:tmp.echo))\n  endif\n  echon substitute(data, \"\\r\\\\ze\\n\", '', 'g')\nendfunction\n\nfunction! s:RunTick(job) abort\n  if type(a:job) == v:t_number\n    return jobwait([a:job], 1)[0] == -1\n  elseif type(a:job) == 8\n    let running = ch_status(a:job) !~# '^closed$\\|^fail$' || job_status(a:job) ==# 'run'\n    sleep 1m\n    return running\n  endif\nendfunction\n\nif !exists('s:edit_jobs')\n  let s:edit_jobs = {}\nendif\nfunction! s:RunWait(state, tmp, job, ...) abort\n  if a:0 && filereadable(a:1)\n    call delete(a:1)\n  endif\n  try\n    if a:tmp.no_more && &more\n      let more = &more\n      let &more = 0\n    endif\n    while get(a:state, 'request', '') !=# 'edit' && s:RunTick(a:job)\n      call s:RunEcho(a:tmp)\n      if !get(a:tmp, 'closed_in')\n        let peek = getchar(1)\n        if peek != 0 && !(has('win32') && peek == 128)\n          let c = getchar()\n          let c = type(c) == type(0) ? nr2char(c) : c\n          if c ==# \"\\<C-D>\" || c ==# \"\\<Esc>\"\n            let a:tmp.closed_in = 1\n            let can_pedit = s:RunCloseIn(a:job) && exists('*setbufline')\n            for winnr in range(1, winnr('$'))\n              if getwinvar(winnr, '&previewwindow') && getbufvar(winbufnr(winnr), '&modified')\n                let can_pedit = 0\n              endif\n            endfor\n            if can_pedit\n              if has_key(a:tmp, 'echo')\n                call remove(a:tmp, 'echo')\n              endif\n              call writefile(['fugitive: aborting edit due to background operation.'], a:state.file . '.exit')\n              exe (&splitbelow ? 'botright' : 'topleft') 'silent pedit ++ff=unix' s:fnameescape(a:state.file)\n              let a:state.capture_bufnr = bufnr(a:state.file)\n              call setbufvar(a:state.capture_bufnr, '&modified', 1)\n              let finished = 0\n              redraw!\n              return ''\n            endif\n          else\n            call s:RunSend(a:job, c)\n            if !a:state.pty\n              echon c\n            endif\n          endif\n        endif\n      endif\n    endwhile\n    if !has_key(a:state, 'request') && has_key(a:state, 'job') && exists('*job_status') && job_status(a:job) ==# \"dead\"\n      throw 'fugitive: close callback did not fire; this should never happen'\n    endif\n    call s:RunEcho(a:tmp)\n    if has_key(a:tmp, 'echo')\n      let a:tmp.echo = substitute(a:tmp.echo, \"^\\r\\\\=\\n\", '', '')\n      echo\n    endif\n    let finished = !s:RunEdit(a:state, a:tmp, a:job)\n  finally\n    if exists('l:more')\n      let &more = more\n    endif\n    if !exists('finished')\n      try\n        if a:state.pty && !get(a:tmp, 'closed_in')\n          call s:RunSend(a:job, \"\\<C-C>\")\n        elseif type(a:job) == type(0)\n          call jobstop(a:job)\n        else\n          call job_stop(a:job)\n        endif\n      catch /.*/\n      endtry\n    elseif finished\n      call fugitive#DidChange(a:state)\n    endif\n  endtry\n  return ''\nendfunction\n\nif !exists('s:resume_queue')\n  let s:resume_queue = []\nendif\nfunction! fugitive#Resume() abort\n  while len(s:resume_queue)\n    let enqueued = remove(s:resume_queue, 0)\n    if enqueued[2] isnot# ''\n      try\n        call call('s:RunWait', enqueued)\n      endtry\n    endif\n  endwhile\nendfunction\n\nfunction! s:RunBufDelete(bufnr) abort\n  let state = s:TempState(+a:bufnr)\n  if has_key(state, 'job')\n    try\n      if type(state.job) == type(0)\n        call jobstop(state.job)\n      else\n        call job_stop(state.job)\n      endif\n    catch\n    endtry\n  endif\n  if has_key(s:edit_jobs, a:bufnr) |\n    call add(s:resume_queue, remove(s:edit_jobs, a:bufnr))\n    call feedkeys(\"\\<C-\\>\\<C-N>:redraw!|call delete(\" . string(s:resume_queue[-1][0].file . '.edit') .\n          \\ \")|call fugitive#Resume()|checktime\\r\", 'n')\n  endif\nendfunction\n\naugroup fugitive_job\n  autocmd!\n  autocmd BufDelete * call s:RunBufDelete(+expand('<abuf>'))\n  autocmd VimLeave *\n        \\ for s:jobbuf in keys(s:edit_jobs) |\n        \\   call writefile(['Aborting edit due to Vim exit.'], s:edit_jobs[s:jobbuf][0].file . '.exit') |\n        \\   redraw! |\n        \\   call call('s:RunWait', remove(s:edit_jobs, s:jobbuf)) |\n        \\ endfor\naugroup END\n\nfunction! fugitive#CanPty() abort\n  return get(g:, 'fugitive_pty_debug_override',\n        \\ has('unix') && !has('win32unix') && (has('patch-8.0.0744') || has('nvim')) && fugitive#GitVersion() !~# '\\.windows\\>')\nendfunction\n\nfunction! fugitive#PagerFor(argv, ...) abort\n  let args = a:argv\n  if empty(args)\n    return 0\n  elseif (args[0] ==# 'help' || get(args, 1, '') ==# '--help') && !s:HasOpt(args, '--web')\n    return 1\n  endif\n  if args[0] ==# 'config' && (s:HasOpt(args, '-e', '--edit') ||\n        \\   !s:HasOpt(args, '--list', '--get-all', '--get-regexp', '--get-urlmatch')) ||\n        \\ args[0] =~# '^\\%(tag\\|branch\\)$' && (\n        \\    s:HasOpt(args, '--edit-description', '--unset-upstream', '-m', '-M', '--move', '-c', '-C', '--copy', '-d', '-D', '--delete') ||\n        \\   len(filter(args[1:-1], 'v:val =~# \"^[^-]\\\\|^--set-upstream-to=\"')) &&\n        \\   !s:HasOpt(args, '--contains', '--no-contains', '--merged', '--no-merged', '--points-at'))\n    return 0\n  endif\n  let config = a:0 ? a:1 : fugitive#Config()\n  let value = get(fugitive#ConfigGetAll('pager.' . args[0], config), 0, -1)\n  if value =~# '^\\%(true\\|yes\\|on\\|1\\)$'\n    return 1\n  elseif value =~# '^\\%(false\\|no|off\\|0\\|\\)$'\n    return 0\n  elseif type(value) == type('')\n    return value\n  elseif args[0] =~# '^\\%(branch\\|config\\|diff\\|grep\\|log\\|range-diff\\|shortlog\\|show\\|tag\\|whatchanged\\)$' ||\n        \\ (args[0] ==# 'stash' && get(args, 1, '') ==# 'show') ||\n        \\ (args[0] ==# 'reflog' && get(args, 1, '') !~# '^\\%(expire\\|delete\\|exists\\)$') ||\n        \\ (args[0] ==# 'am' && s:HasOpt(args, '--show-current-patch'))\n    return 1\n  else\n    return 0\n  endif\nendfunction\n\nlet s:disable_colors = []\nfor s:colortype in ['advice', 'branch', 'diff', 'grep', 'interactive', 'pager', 'push', 'remote', 'showBranch', 'status', 'transport', 'ui']\n  call extend(s:disable_colors, ['-c', 'color.' . s:colortype . '=false'])\nendfor\nunlet s:colortype\nfunction! fugitive#Command(line1, line2, range, bang, mods, arg, ...) abort\n  exe s:VersionCheck()\n  let dir = call('s:Dir', a:000)\n  if len(dir)\n    exe s:DirCheck(dir)\n  endif\n  let config = copy(fugitive#Config(dir))\n  let curwin = a:arg =~# '^++curwin\\>' || !a:line2\n  let [args, after] = s:SplitExpandChain(substitute(a:arg, '^++curwin\\>\\s*', '', ''), s:Tree(dir))\n  let flags = []\n  let pager = -1\n  let explicit_pathspec_option = 0\n  let did_expand_alias = 0\n  while len(args)\n    if args[0] ==# '-c' && len(args) > 1\n      call extend(flags, remove(args, 0, 1))\n    elseif args[0] =~# '^-p$\\|^--paginate$'\n      let pager = 2\n      call remove(args, 0)\n    elseif args[0] =~# '^-P$\\|^--no-pager$'\n      let pager = 0\n      call remove(args, 0)\n    elseif args[0] =~# '^--\\%([[:lower:]-]\\+-pathspecs\\)$'\n      let explicit_pathspec_option = 1\n      call add(flags, remove(args, 0))\n    elseif args[0] =~# '^\\%(--no-optional-locks\\)$'\n      call add(flags, remove(args, 0))\n    elseif args[0] =~# '^-C$\\|^--\\%(exec-path=\\|git-dir=\\|work-tree=\\|bare$\\)'\n      return 'echoerr ' . string('fugitive: ' . args[0] . ' is not supported')\n    elseif did_expand_alias\n      break\n    else\n      let alias = FugitiveConfigGet('alias.' . get(args, 0, ''), config)\n      if get(args, 1, '') !=# '--help' && alias !~# '^$\\|^!\\|[\\\"'']' && !filereadable(s:VimExecPath() . '/git-' . args[0])\n            \\ && !(has('win32') && filereadable(s:VimExecPath() . '/git-' . args[0] . '.exe'))\n        call remove(args, 0)\n        call extend(args, split(alias, '\\s\\+'), 'keep')\n        let did_expand_alias = 1\n      else\n        break\n      endif\n    endif\n  endwhile\n  if !explicit_pathspec_option\n    call insert(flags, '--no-literal-pathspecs')\n  endif\n  let no_pager = pager is# 0\n  if no_pager\n    call add(flags, '--no-pager')\n  endif\n  let env = {}\n  let i = 0\n  while i < len(flags) - 1\n    if flags[i] ==# '-c'\n      let i += 1\n      let config_name = tolower(matchstr(flags[i], '^[^=]\\+'))\n      if has_key(s:prepare_env, config_name) && flags[i] =~# '=.'\n        let env[s:prepare_env[config_name]] = matchstr(flags[i], '=\\zs.*')\n      endif\n      if flags[i] =~# '='\n        let config[config_name] = [matchstr(flags[i], '=\\zs.*')]\n      else\n        let config[config_name] = [1]\n      endif\n    endif\n    let i += 1\n  endwhile\n  let options = {'git': s:UserCommandList(), 'git_dir': s:GitDir(dir), 'flags': flags, 'curwin': curwin}\n  if empty(args) && pager is# -1\n    let cmd = s:StatusCommand(a:line1, a:line2, a:range, curwin ? 0 : a:line2, a:bang, a:mods, '', '', [], options)\n    return (empty(cmd) ? 'exe' : cmd) . after\n  endif\n  let name = substitute(get(args, 0, ''), '\\%(^\\|-\\)\\(\\l\\)', '\\u\\1', 'g')\n  if pager is# -1 && name =~# '^\\a\\+$' && exists('*s:' . name . 'Subcommand') && get(args, 1, '') !=# '--help'\n    try\n      let overrides = s:{name}Subcommand(a:line1, a:line2, a:range, a:bang, a:mods, extend({'subcommand': args[0], 'subcommand_args': args[1:-1]}, options))\n      if type(overrides) == type('')\n        return 'exe ' . string(overrides) . after\n      endif\n      let args = [get(overrides, 'command', args[0])] + get(overrides, 'insert_args', []) + args[1:-1]\n    catch /^fugitive:/\n      return 'echoerr ' . string(v:exception)\n    endtry\n  else\n    let overrides = {}\n  endif\n  call extend(env, get(overrides, 'env', {}))\n  call s:PrepareEnv(env, dir)\n  if pager is# -1\n    let pager = fugitive#PagerFor(args, config)\n  endif\n  let wants_terminal = type(pager) ==# type('') ||\n        \\ (s:HasOpt(args, ['add', 'checkout', 'commit', 'reset', 'restore', 'stage', 'stash'], '-p', '--patch') ||\n        \\ s:HasOpt(args, ['add', 'clean', 'stage'], '-i', '--interactive')) && pager is# 0\n  if wants_terminal\n    let mods = substitute(s:Mods(a:mods), '\\<tab\\>', '-tab', 'g')\n    let assign = len(dir) ? \"|call FugitiveDetect({'git_dir':\" . string(options.git_dir) . '})' : ''\n    let argv = s:UserCommandList(options) + args\n    let term_opts = len(env) ? {'env': env} : {}\n    if has('nvim')\n      call fugitive#Autowrite()\n      return mods . (curwin ? 'enew' : 'new') . '|call termopen(' . string(argv) . ', ' . string(term_opts) . ')' . assign . '|startinsert' . after\n    elseif exists('*term_start')\n      call fugitive#Autowrite()\n      if curwin\n        let term_opts.curwin = 1\n      endif\n      return mods . 'call term_start(' . string(argv) . ', ' . string(term_opts) . ')' . assign . after\n    endif\n  endif\n  let state = {\n        \\ 'git': options.git,\n        \\ 'flags': flags,\n        \\ 'args': args,\n        \\ 'git_dir': options.git_dir,\n        \\ 'cwd': s:UserCommandCwd(dir),\n        \\ 'filetype': 'git',\n        \\ 'mods': s:Mods(a:mods),\n        \\ 'file': s:Resolve(tempname())}\n  let allow_pty = 1\n  let after_edit = ''\n  let stream = 0\n  if a:bang && pager isnot# 2\n    let state.pager = pager\n    let pager = 1\n    let stream = exists('*setbufline')\n    let do_edit = substitute(s:Mods(a:mods, 'Edge'), '\\<tab\\>', '-tab', 'g') . 'pedit!'\n  elseif pager\n    let allow_pty = get(args, 0, '') is# 'shortlog'\n    if pager is# 2 && a:bang && a:line2 >= 0\n      let [do_edit, after_edit] = s:ReadPrepare(a:line1, a:line2, a:range, a:mods)\n    elseif pager is# 2 && a:bang\n      let do_edit = s:Mods(a:mods, 'SpanOrigin') . 'pedit'\n    elseif !curwin\n      let do_edit = s:Mods(a:mods, 'SpanOrigin') . 'split'\n    else\n      let do_edit = s:Mods(a:mods) . 'edit'\n      call s:BlurStatus()\n    endif\n    call extend(env, {'COLUMNS': '' . get(g:, 'fugitive_columns', 80)}, 'keep')\n  endif\n  if s:run_jobs\n    call extend(env, {'COLUMNS': '' . (&columns - 1)}, 'keep')\n    let state.pty = allow_pty && fugitive#CanPty()\n    if !state.pty\n      let args = s:AskPassArgs(dir) + args\n    endif\n    let tmp = {\n          \\ 'no_more': no_pager || get(overrides, 'no_more'),\n          \\ 'line_count': 0,\n          \\ 'err': '',\n          \\ 'out': '',\n          \\ 'escape': ''}\n    let env.FUGITIVE = state.file\n    let editor = 'sh ' . s:TempScript(\n          \\ '[ -f \"$FUGITIVE.exit\" ] && cat \"$FUGITIVE.exit\" >&2 && exit 1',\n          \\ 'echo \"$1\" > \"$FUGITIVE.edit\"',\n          \\ 'printf \"\\033]51;fugitive:edit\\007\" >&2',\n          \\ 'while [ -f \"$FUGITIVE.edit\" -a ! -f \"$FUGITIVE.exit\" ]; do sleep 0.05 2>/dev/null || sleep 1; done',\n          \\ 'exit 0')\n    call extend(env, {\n          \\ 'NO_COLOR': '1',\n          \\ 'GIT_EDITOR': editor,\n          \\ 'GIT_SEQUENCE_EDITOR': editor,\n          \\ 'GIT_PAGER': 'cat',\n          \\ 'PAGER': 'cat'}, 'keep')\n    if s:executable('col')\n      let env.MANPAGER = 'col -b'\n    endif\n    if len($GPG_TTY) && !has_key(env, 'GPG_TTY')\n      let env.GPG_TTY = ''\n      let did_override_gpg_tty = 1\n    endif\n    if stream\n      call writefile(['fugitive: aborting edit due to background operation.'], state.file . '.exit')\n    elseif pager\n      call writefile(['fugitive: aborting edit due to use of pager.'], state.file . '.exit')\n      let after = '|' . do_edit . ' ' . s:fnameescape(state.file) . after_edit . after\n    else\n      let env.GIT_MERGE_AUTOEDIT = '1'\n      let tmp.echo = ''\n    endif\n    let args = s:disable_colors + flags + ['-c', 'advice.waitingForEditor=false'] + args\n    let argv = s:UserCommandList({'git': options.git, 'git_dir': options.git_dir}) + args\n    let [argv, jobopts] = s:JobOpts(argv, env)\n    call fugitive#Autowrite()\n    call writefile([], state.file, 'b')\n    call s:RunSave(state)\n    if has_key(tmp, 'echo')\n      echo \"\"\n    endif\n    if exists('*ch_close_in')\n      call extend(jobopts, {\n            \\ 'mode': 'raw',\n            \\ 'out_cb': function('s:RunReceive', [state, tmp, 'out']),\n            \\ 'err_cb': function('s:RunReceive', [state, tmp, 'err']),\n            \\ 'close_cb': function('s:RunClose', [state, tmp]),\n            \\ 'exit_cb': function('s:RunExit', [state, tmp]),\n            \\ })\n      if state.pty\n        let jobopts.pty = 1\n      endif\n      let job = job_start(argv, jobopts)\n    else\n      let job = jobstart(argv, extend(jobopts, {\n            \\ 'pty': state.pty,\n            \\ 'TERM': 'dumb',\n            \\ 'stdout_buffered': pager,\n            \\ 'stderr_buffered': pager,\n            \\ 'on_stdout': function('s:RunReceive', [state, tmp, 'out']),\n            \\ 'on_stderr': function('s:RunReceive', [state, tmp, 'err']),\n            \\ 'on_exit': function('s:RunClose', [state, tmp]),\n            \\ }))\n    endif\n    let state.job = job\n    if pager\n      let tmp.closed_in = 1\n      call s:RunCloseIn(job)\n    endif\n    if stream\n      exe 'silent' do_edit '++ff=unix' s:fnameescape(state.file)\n      let state.capture_bufnr = bufnr(state.file)\n      call setbufvar(state.capture_bufnr, '&modified', 1)\n      return (after_edit . after)[1:-1]\n    endif\n    call add(s:resume_queue, [state, tmp, job])\n    return 'call fugitive#Resume()|checktime' . after\n  elseif pager\n    let pre = s:BuildEnvPrefix(env)\n    try\n      if exists('+guioptions') && &guioptions =~# '!'\n        let guioptions = &guioptions\n        set guioptions-=!\n      endif\n      silent! execute '!' . escape(pre . s:shellesc(s:UserCommandList(options) + s:disable_colors + flags + ['--no-pager'] + args), '!#%') .\n            \\ (&shell =~# 'csh' ? ' >& ' . s:shellesc(state.file) : ' > ' . s:shellesc(state.file) . ' 2>&1')\n      let state.exit_status = v:shell_error\n    finally\n      if exists('guioptions')\n        let &guioptions = guioptions\n      endif\n    endtry\n    redraw!\n    call s:RunSave(state)\n    call s:RunFinished(state)\n    return do_edit . ' ' . s:fnameescape(state.file) . after_edit .\n          \\ '|call fugitive#DidChange(fugitive#Result(' . string(state.file) . '))' . after\n  elseif has('win32')\n    return 'echoerr ' . string('fugitive: Vim 8 with job support required to use :Git on Windows')\n  elseif has('gui_running')\n    return 'echoerr ' . string('fugitive: Vim 8 with job support required to use :Git in GVim')\n  else\n    if !explicit_pathspec_option && get(options.flags, 0, '') ==# '--no-literal-pathspecs'\n      call remove(options.flags, 0)\n    endif\n    if exists('l:did_override_gpg_tty')\n      call remove(env, 'GPG_TTY')\n    endif\n    let cmd = s:BuildEnvPrefix(env) . s:shellesc(s:UserCommandList(options) + args)\n    let after = '|call fugitive#DidChange(' . string(dir) . ')' . after\n    if !wants_terminal && (no_pager || index(['add', 'clean', 'reset', 'restore', 'stage'], get(args, 0, '')) >= 0 || s:HasOpt(args, ['checkout'], '-q', '--quiet', '--no-progress'))\n      let output = substitute(s:SystemError(cmd)[0], \"\\n$\", '', '')\n      if len(output)\n        try\n          if &more && no_pager\n            let more = 1\n            set nomore\n          endif\n          echo substitute(output, \"\\n$\", \"\", \"\")\n        finally\n          if exists('l:more')\n            set more\n          endif\n        endtry\n      endif\n      return 'checktime' . after\n    else\n      return 'exe ' . string('noautocmd !' . escape(cmd, '!#%')) . after\n    endif\n  endif\nendfunction\n\nlet s:exec_paths = {}\nfunction! s:ExecPath() abort\n  let git = s:GitShellCmd()\n  if !has_key(s:exec_paths, git)\n    let path = get(s:JobExecute(s:GitCmd() + ['--exec-path'], {}, [], [], {}).stdout, 0, '')\n    let s:exec_paths[git] = [path, FugitiveVimPath(path)]\n  endif\n  return s:exec_paths[git]\nendfunction\n\nfunction! s:VimExecPath() abort\n  return s:ExecPath()[1]\nendfunction\n\nlet s:subcommands_before_2_5 = [\n      \\ 'add', 'am', 'apply', 'archive', 'bisect', 'blame', 'branch', 'bundle',\n      \\ 'checkout', 'cherry', 'cherry-pick', 'citool', 'clean', 'clone', 'commit', 'config',\n      \\ 'describe', 'diff', 'difftool', 'fetch', 'format-patch', 'fsck',\n      \\ 'gc', 'grep', 'gui', 'help', 'init', 'instaweb', 'log',\n      \\ 'merge', 'mergetool', 'mv', 'notes', 'pull', 'push',\n      \\ 'rebase', 'reflog', 'remote', 'repack', 'replace', 'request-pull', 'reset', 'revert', 'rm',\n      \\ 'send-email', 'shortlog', 'show', 'show-branch', 'stash', 'stage', 'status', 'submodule',\n      \\ 'tag', 'whatchanged',\n      \\ ]\nlet s:path_subcommands = {}\nfunction! s:CompletableSubcommands(dir) abort\n  let c_exec_path = s:cpath(s:VimExecPath())\n  if !has_key(s:path_subcommands, c_exec_path)\n    if fugitive#GitVersion(2, 18)\n      let [lines, exec_error] = s:LinesError([a:dir, '--list-cmds=list-mainporcelain,nohelpers,list-complete,others'])\n      call filter(lines, 'v:val =~# \"^\\\\S\\\\+$\"')\n      if !exec_error && len(lines)\n        let s:path_subcommands[c_exec_path] = lines\n      else\n        let s:path_subcommands[c_exec_path] = s:subcommands_before_2_5 +\n              \\ ['maintenance', 'prune', 'range-diff', 'restore', 'sparse-checkout', 'switch', 'worktree']\n      endif\n    else\n      let s:path_subcommands[c_exec_path] = s:subcommands_before_2_5 +\n            \\ (fugitive#GitVersion(2, 5) ? ['worktree'] : [])\n    endif\n  endif\n  let commands = copy(s:path_subcommands[c_exec_path])\n  call extend(commands, keys(fugitive#ConfigGetRegexp('^alias\\.\\zs[^.]\\+$', a:dir)))\n  let configured = split(FugitiveConfigGet('completion.commands', a:dir), '\\s\\+')\n  let rejected = {}\n  for command in configured\n    if command =~# '^-.'\n      let rejected[strpart(command, 1)] = 1\n    endif\n  endfor\n  call filter(configured, 'v:val !~# \"^-\"')\n  let results = filter(sort(commands + configured), '!has_key(rejected, v:val)')\n  if exists('*uniq')\n    return uniq(results)\n  else\n    let i = 1\n    while i < len(results)\n      if results[i] ==# results[i-1]\n        call remove(results, i)\n      else\n        let i += 1\n      endif\n    endwhile\n    return results\n  endif\nendfunction\n\nfunction! fugitive#Complete(lead, ...) abort\n  let dir = a:0 == 1 ? a:1 : a:0 >= 3 ? s:Dir(a:3) : s:Dir()\n  let root = a:0 >= 4 ? a:4 : s:Tree(s:Dir())\n  let pre = a:0 > 1 ? strpart(a:1, 0, a:2) : ''\n  let subcmd = matchstr(pre, '\\u\\w*[! ] *\\%(\\%(++\\S\\+\\|--\\S\\+-pathspecs\\|-c\\s\\+\\S\\+\\)\\s\\+\\)*\\zs[[:alnum:]][[:alnum:]-]*\\ze ')\n  if empty(subcmd) && a:lead =~# '^+'\n    let results = ['++curwin']\n  elseif empty(subcmd) && a:lead =~# '^-'\n    let results = ['--literal-pathspecs', '--no-literal-pathspecs', '--glob-pathspecs', '--noglob-pathspecs', '--icase-pathspecs', '--no-optional-locks']\n  elseif empty(subcmd)\n    let results = s:CompletableSubcommands(dir)\n  elseif a:0 ==# 2 && subcmd =~# '^\\%(commit\\|revert\\|push\\|fetch\\|pull\\|merge\\|rebase\\|bisect\\)$'\n    let cmdline = substitute(a:1, '\\u\\w*\\([! ] *\\)' . subcmd, 'G' . subcmd, '')\n    let caps_subcmd = substitute(subcmd, '\\%(^\\|-\\)\\l', '\\u&', 'g')\n    return fugitive#{caps_subcmd}Complete(a:lead, cmdline, a:2 + len(cmdline) - len(a:1), dir, root)\n  elseif pre =~# ' -- '\n    return fugitive#CompletePath(a:lead, a:1, a:2, dir, root)\n  elseif a:lead =~# '^-'\n    let results = split(s:ChompDefault('', [dir, subcmd, '--git-completion-helper']), ' ')\n  else\n    return fugitive#CompleteObject(a:lead, a:1, a:2, dir, root)\n  endif\n  return filter(results, 'strpart(v:val, 0, strlen(a:lead)) ==# a:lead')\nendfunction\n\nfunction! fugitive#CompleteForWorkingDir(A, L, P, ...) abort\n  let path = a:0 ? a:1 : getcwd()\n  return fugitive#Complete(a:A, a:L, a:P, FugitiveExtractGitDir(path), path)\nendfunction\n\n\" Section: :Gcd, :Glcd\n\nfunction! fugitive#CdComplete(A, L, P) abort\n  return filter(fugitive#CompletePath(a:A), 'v:val =~# \"/$\"')\nendfunction\n\nfunction! fugitive#Cd(path, ...) abort\n  exe s:VersionCheck()\n  let path = substitute(a:path, '^:/:\\=\\|^:(\\%(top\\|top,literal\\|literal,top\\|literal\\))', '', '')\n  if path !~# '^/\\|^\\a\\+:\\|^\\.\\.\\=\\%(/\\|$\\)'\n    let dir = s:Dir()\n    exe s:DirCheck(dir)\n    let path = (empty(s:Tree(dir)) ? dir : s:Tree(dir)) . '/' . path\n  endif\n  return (a:0 && a:1 ? 'lcd ' : 'cd ') . fnameescape(s:VimSlash(path))\nendfunction\n\n\" Section: :Gstatus\n\nfunction! s:StatusCommand(line1, line2, range, count, bang, mods, reg, arg, args, ...) abort\n  let dir = a:0 ? s:Dir(a:1) : s:Dir()\n  exe s:DirCheck(dir)\n  try\n    let mods = s:Mods(a:mods, 'Edge')\n    let file = fugitive#Find(':', dir)\n    let arg = ' +setl\\ foldmarker=<<<<<<<<,>>>>>>>>\\|let\\ w:fugitive_status=FugitiveGitDir() ' .\n          \\ s:fnameescape(file)\n    for tabnr in [tabpagenr()] + (mods =~# '\\<tab\\>' ? range(1, tabpagenr('$')) : [])\n      let bufs = tabpagebuflist(tabnr)\n      for winnr in range(1, tabpagewinnr(tabnr, '$'))\n        if s:cpath(file, fnamemodify(bufname(bufs[winnr-1]), ':p'))\n          if tabnr == tabpagenr() && winnr == winnr()\n            call s:ReloadStatus()\n          else\n            call s:ExpireStatus(dir)\n            exe tabnr . 'tabnext'\n            exe winnr . 'wincmd w'\n          endif\n          let w:fugitive_status = dir\n          1\n          return ''\n        endif\n      endfor\n    endfor\n    if a:count ==# 0\n      return mods . 'edit' . (a:bang ? '!' : '') . arg\n    elseif a:bang\n      return mods . 'pedit' . arg . '|wincmd P'\n    else\n      return mods . 'keepalt split' . arg\n    endif\n  catch /^fugitive:/\n    return 'echoerr ' . string(v:exception)\n  endtry\n  return ''\nendfunction\n\nfunction! s:StageJump(offset, section, ...) abort\n  let line = search('^\\%(' . a:section . '\\)', 'nw')\n  if !line && a:0\n    let line = search('^\\%(' . a:1 . '\\)', 'nw')\n  endif\n  if line\n    exe line\n    if a:offset\n      for i in range(a:offset)\n        call search(s:file_commit_pattern . '\\|^$', 'W')\n        if empty(getline('.')) && a:0 && getline(line('.') + 1) =~# '^\\%(' . a:1 . '\\)'\n          call search(s:file_commit_pattern . '\\|^$', 'W')\n        endif\n        if empty(getline('.'))\n          return ''\n        endif\n      endfor\n      call s:StageReveal()\n    else\n      call s:StageReveal()\n      +\n    endif\n  endif\n  return ''\nendfunction\n\nfunction! s:StageSeek(info, fallback) abort\n  let info = a:info\n  if empty(info.heading)\n    return a:fallback\n  endif\n  let line = search('^' . escape(info.heading, '^$.*[]~\\') . ' (\\d\\++\\=)$', 'wn')\n  if !line\n    for section in get({'Staged': ['Unstaged', 'Untracked'], 'Unstaged': ['Untracked', 'Staged'], 'Untracked': ['Unstaged', 'Staged']}, info.section, [])\n      let line = search('^' . section, 'wn')\n      if line\n        return line + (info.index > 0 ? 1 : 0)\n      endif\n    endfor\n    return 1\n  endif\n  let i = 0\n  while len(getline(line))\n    let filename = matchstr(getline(line), '^[A-Z?] \\zs.*')\n    if len(filename) &&\n          \\ ((info.filename[-1:-1] ==# '/' && filename[0 : len(info.filename) - 1] ==# info.filename) ||\n          \\ (filename[-1:-1] ==# '/' && filename ==# info.filename[0 : len(filename) - 1]) ||\n          \\ filename ==# info.filename)\n      if info.offset < 0\n        return line\n      else\n        if getline(line+1) !~# '^@'\n          exe s:StageInline('show', line)\n        endif\n        if getline(line+1) !~# '^@'\n          return line\n        endif\n        let type = info.sigil ==# '-' ? '-' : '+'\n        let offset = -1\n        while offset < info.offset\n          let line += 1\n          if getline(line) =~# '^@'\n            let offset = +matchstr(getline(line), type . '\\zs\\d\\+') - 1\n          elseif getline(line) =~# '^[ ' . type . ']'\n            let offset += 1\n          elseif getline(line) !~# '^[ @\\+-]'\n            return line - 1\n          endif\n        endwhile\n        return line\n      endif\n    endif\n    let commit = matchstr(getline(line), '^\\%(\\%(\\x\\x\\x\\)\\@!\\l\\+\\s\\+\\)\\=\\zs[0-9a-f]\\+')\n    if len(commit) && commit ==# info.commit\n      return line\n    endif\n    if i ==# info.index\n      let backup = line\n    endif\n    let i += getline(line) !~# '^[ @\\+-]'\n    let line += 1\n  endwhile\n  return exists('backup') ? backup : line - 1\nendfunction\n\nfunction! s:DoAutocmdChanged(dir) abort\n  let dir = a:dir is# -2 ? '' : FugitiveGitDir(a:dir)\n  if empty(dir) || !exists('#User#FugitiveChanged') || exists('g:fugitive_event')\n    return ''\n  endif\n  try\n    let g:fugitive_event = dir\n    if type(a:dir) == type({}) && has_key(a:dir, 'args') && has_key(a:dir, 'exit_status')\n      let g:fugitive_result = a:dir\n    endif\n    exe s:DoAutocmd('User FugitiveChanged')\n  finally\n    unlet! g:fugitive_event g:fugitive_result\n    \" Force statusline reload with the buffer's Git dir\n    if dir isnot# FugitiveGitDir()\n      let &l:ro = &l:ro\n    endif\n  endtry\n  return ''\nendfunction\n\nfunction! s:ReloadStatusBuffer() abort\n  if get(b:, 'fugitive_type', '') !=# 'index' || !empty(get(b:, 'fugitive_loading'))\n    return ''\n  endif\n  let original_lnum = line('.')\n  let info = s:StageInfo(original_lnum)\n  exe fugitive#BufReadStatus(0)\n  call setpos('.', [0, s:StageSeek(info, original_lnum), 1, 0])\n  return ''\nendfunction\n\nfunction! s:ReloadStatus() abort\n  call s:ExpireStatus(-1)\n  call s:ReloadStatusBuffer()\n  exe s:DoAutocmdChanged(-1)\n  return ''\nendfunction\n\nlet s:last_time = reltime()\nif !exists('s:last_times')\n  let s:last_times = {}\nendif\n\nfunction! s:ExpireStatus(bufnr) abort\n  if a:bufnr is# -2 || a:bufnr is# 0\n    let s:head_cache = {}\n    let s:last_time = reltime()\n    return ''\n  endif\n  let head_file = fugitive#Find('.git/HEAD', a:bufnr)\n  if !empty(head_file)\n    let s:last_times[s:Tree(a:bufnr) . '/'] = reltime()\n    if has_key(s:head_cache, head_file)\n      call remove(s:head_cache, head_file)\n    endif\n  endif\n  return ''\nendfunction\n\nfunction! s:ReloadWinStatus(...) abort\n  if get(b:, 'fugitive_type', '') !=# 'index' || !empty(get(b:, 'fugitive_loading')) || &modified\n    return\n  endif\n  if !exists('b:fugitive_status.reltime')\n    exe call('s:ReloadStatusBuffer', a:000)\n    return\n  endif\n  let t = b:fugitive_status.reltime\n  if reltimestr(reltime(s:last_time, t)) =~# '-\\|\\d\\{10\\}\\.' ||\n        \\ reltimestr(reltime(get(s:last_times, s:Tree() . '/', t), t)) =~# '-\\|\\d\\{10\\}\\.'\n    exe call('s:ReloadStatusBuffer', a:000)\n  endif\nendfunction\n\nfunction! s:ReloadTabStatus() abort\n  if !exists('g:fugitive_did_change_at')\n    return\n  elseif exists('t:fugitive_reloaded_at')\n    let time_ahead = reltime(g:fugitive_did_change_at, t:fugitive_reloaded_at)\n    if reltimefloat(time_ahead) >= 0\n      return\n    endif\n  endif\n  let t:fugitive_reloaded_at = reltime()\n  let winnr = 1\n  while winnr <= winnr('$')\n    if getbufvar(winbufnr(winnr), 'fugitive_type') ==# 'index'\n      if winnr != winnr()\n        execute 'noautocmd' winnr.'wincmd w'\n        let restorewinnr = 1\n      endif\n      try\n        call s:ReloadWinStatus()\n      finally\n        if exists('restorewinnr')\n          unlet restorewinnr\n          noautocmd wincmd p\n        endif\n      endtry\n    endif\n    let winnr += 1\n  endwhile\nendfunction\n\nfunction! fugitive#DidChange(...) abort\n  call s:ExpireStatus(a:0 ? a:1 : -1)\n  if a:0 > 1 ? a:2 : (!a:0 || a:1 isnot# 0)\n    let g:fugitive_did_change_at = reltime()\n    call s:ReloadTabStatus()\n  else\n    call s:ReloadWinStatus()\n    return ''\n  endif\n  exe s:DoAutocmdChanged(a:0 ? a:1 : -1)\n  return ''\nendfunction\n\nfunction! fugitive#ReloadStatus(...) abort\n  return call('fugitive#DidChange', a:000)\nendfunction\n\nfunction! fugitive#EfmDir(...) abort\n  let dir = matchstr(a:0 ? a:1 : &errorformat, '\\c,%\\\\&\\%(git\\|fugitive\\)_\\=dir=\\zs\\%(\\\\.\\|[^,]\\)*')\n  let dir = substitute(dir, '%%', '%', 'g')\n  let dir = substitute(dir, '\\\\\\ze[\\,]', '', 'g')\n  return dir\nendfunction\n\naugroup fugitive_status\n  autocmd!\n  autocmd BufWritePost         * call fugitive#DidChange(+expand('<abuf>'), 0)\n  autocmd User FileChmodPost,FileUnlinkPost call fugitive#DidChange(+expand('<abuf>'), 0)\n  autocmd ShellCmdPost,ShellFilterPost * nested call fugitive#DidChange(0)\n  autocmd BufDelete * nested\n        \\ if getbufvar(+expand('<abuf>'), 'buftype') ==# 'terminal' |\n        \\   if !empty(FugitiveGitDir(+expand('<abuf>'))) |\n        \\     call fugitive#DidChange(+expand('<abuf>')) |\n        \\   else |\n        \\     call fugitive#DidChange(0) |\n        \\  endif |\n        \\ endif\n  autocmd QuickFixCmdPost make,lmake,[cl]file,[cl]getfile nested\n        \\ call fugitive#DidChange(fugitive#EfmDir())\n  autocmd FocusGained        *\n        \\ if get(g:, 'fugitive_focus_gained', !has('win32')) |\n        \\   call fugitive#DidChange(0) |\n        \\ endif\n  autocmd BufEnter index,index.lock,fugitive://*//\n        \\ call s:ReloadWinStatus()\n  autocmd TabEnter *\n        \\ call s:ReloadTabStatus()\naugroup END\n\nfunction! s:StatusSectionFile(heading, filename) abort\n  return get(get(get(get(b:, 'fugitive_status', {}), 'files', {}), a:heading, {}), a:filename, {})\nendfunction\n\nfunction! s:StageInfo(...) abort\n  let lnum = a:0 ? a:1 : line('.')\n  let sigil = matchstr(getline(lnum), '^[ @\\+-]')\n  let offset = -1\n  if len(sigil)\n    let [lnum, old_lnum, new_lnum] = s:HunkPosition(lnum)\n    let offset = sigil ==# '-' ? old_lnum : new_lnum\n    while getline(lnum) =~# '^[ @\\+-]'\n      let lnum -= 1\n    endwhile\n  endif\n  let slnum = lnum + 1\n  let heading = ''\n  let index = 0\n  while len(getline(slnum - 1)) && empty(heading)\n    let slnum -= 1\n    let heading = matchstr(getline(slnum), '^\\u\\l\\+.\\{-\\}\\ze (\\d\\++\\=)$')\n    if empty(heading) && getline(slnum) !~# '^[ @\\+-]'\n      let index += 1\n    endif\n  endwhile\n  let text = matchstr(getline(lnum), '^[A-Z?] \\zs.*')\n  let file = s:StatusSectionFile(heading, text)\n  let relative = get(file, 'relative', len(text) ? [text] : [])\n  return {'section': matchstr(heading, '^\\u\\l\\+'),\n        \\ 'heading': heading,\n        \\ 'sigil': sigil,\n        \\ 'offset': offset,\n        \\ 'filename': text,\n        \\ 'relative': copy(relative),\n        \\ 'paths': map(copy(relative), 's:Tree() . \"/\" . v:val'),\n        \\ 'commit': matchstr(getline(lnum), '^\\%(\\%(\\x\\x\\x\\)\\@!\\l\\+\\s\\+\\)\\=\\zs[0-9a-f]\\{4,\\}\\ze '),\n        \\ 'status': matchstr(getline(lnum), '^[A-Z?]\\ze \\|^\\%(\\x\\x\\x\\)\\@!\\l\\+\\ze [0-9a-f]'),\n        \\ 'submodule': get(file, 'submodule', ''),\n        \\ 'index': index}\nendfunction\n\nfunction! s:Selection(arg1, ...) abort\n  if a:arg1 ==# 'n'\n    let arg1 = line('.')\n    let arg2 = -v:count\n  elseif a:arg1 ==# 'v'\n    let arg1 = line(\"'<\")\n    let arg2 = line(\"'>\")\n  else\n    let arg1 = a:arg1\n    let arg2 = a:0 ? a:1 : 0\n  endif\n  let first = arg1\n  if arg2 < 0\n    let last = first - arg2 - 1\n  elseif arg2 > 0\n    let last = arg2\n  else\n    let last = first\n  endif\n  while first <= line('$') && getline(first) =~# '^$\\|^[A-Z][a-z]'\n    let first += 1\n  endwhile\n  if first > last || &filetype !=# 'fugitive'\n    return []\n  endif\n  let flnum = first\n  while getline(flnum) =~# '^[ @\\+-]'\n    let flnum -= 1\n  endwhile\n  let slnum = flnum + 1\n  let heading = ''\n  let index = 0\n  while empty(heading)\n    let slnum -= 1\n    let heading = matchstr(getline(slnum), '^\\u\\l\\+.\\{-\\}\\ze (\\d\\++\\=)$')\n    if empty(heading) && getline(slnum) !~# '^[ @\\+-]'\n      let index += 1\n    endif\n  endwhile\n  let results = []\n  let template = {\n        \\ 'heading': heading,\n        \\ 'section': matchstr(heading, '^\\u\\l\\+'),\n        \\ 'filename': '',\n        \\ 'relative': [],\n        \\ 'paths': [],\n        \\ 'commit': '',\n        \\ 'status': '',\n        \\ 'patch': 0,\n        \\ 'index': index}\n  let line = getline(flnum)\n  let lnum = first - (arg1 == flnum ? 0 : 1)\n  let root = s:Tree() . '/'\n  while lnum <= last\n    let heading = matchstr(line, '^\\u\\l\\+\\ze.\\{-\\}\\ze (\\d\\++\\=)$')\n    if len(heading)\n      let template.heading = heading\n      let template.section = matchstr(heading, '^\\u\\l\\+')\n      let template.index = 0\n    elseif line =~# '^[ @\\+-]'\n      let template.index -= 1\n      if !results[-1].patch\n        let results[-1].patch = lnum\n      endif\n      let results[-1].lnum = lnum\n    elseif line =~# '^[A-Z?] '\n      let text = matchstr(line, '^[A-Z?] \\zs.*')\n      let file = s:StatusSectionFile(template.heading, text)\n      let relative = get(file, 'relative', len(text) ? [text] : [])\n      call add(results, extend(deepcopy(template), {\n            \\ 'lnum': lnum,\n            \\ 'filename': text,\n            \\ 'relative': copy(relative),\n            \\ 'paths': map(copy(relative), 'root . v:val'),\n            \\ 'status': matchstr(line, '^[A-Z?]'),\n            \\ }))\n    elseif line =~# '^\\x\\x\\x\\+ '\n      call add(results, extend({\n            \\ 'lnum': lnum,\n            \\ 'commit': matchstr(line, '^\\x\\x\\x\\+'),\n            \\ }, template, 'keep'))\n    elseif line =~# '^\\l\\+ \\x\\x\\x\\+ '\n      call add(results, extend({\n            \\ 'lnum': lnum,\n            \\ 'commit': matchstr(line, '^\\l\\+ \\zs\\x\\x\\x\\+'),\n            \\ 'status': matchstr(line, '^\\l\\+'),\n            \\ }, template, 'keep'))\n    endif\n    let lnum += 1\n    let template.index += 1\n    let line = getline(lnum)\n  endwhile\n  if len(results) && results[0].patch && arg2 == 0\n    while getline(results[0].patch) =~# '^[ \\+-]'\n      let results[0].patch -= 1\n    endwhile\n    while getline(results[0].lnum + 1) =~# '^[ \\+-]'\n      let results[0].lnum += 1\n    endwhile\n  endif\n  return results\nendfunction\n\nfunction! s:StageArgs(visual) abort\n  let commits = []\n  let paths = []\n  for record in s:Selection(a:visual ? 'v' : 'n')\n    if len(record.commit)\n      call add(commits, record.commit)\n    endif\n    call extend(paths, record.paths)\n  endfor\n  if s:cpath(s:Tree(), getcwd())\n    call map(paths, 'fugitive#Path(v:val, \"./\")')\n  endif\n  return join(map(commits + paths, 's:fnameescape(v:val)'), ' ')\nendfunction\n\nfunction! s:Do(action, visual) abort\n  let line = getline('.')\n  let reload = 0\n  if !a:visual && !v:count && line =~# '^[A-Z][a-z]'\n    let header = matchstr(line, '^\\S\\+\\ze:')\n    if len(header) && exists('*s:Do' . a:action . header . 'Header')\n      let reload = s:Do{a:action}{header}Header(matchstr(line, ': \\zs.*')) > 0\n    else\n      let section = matchstr(line, '^\\S\\+')\n      if exists('*s:Do' . a:action . section . 'Heading')\n        let reload = s:Do{a:action}{section}Heading(line) > 0\n      endif\n    endif\n    return reload ? s:ReloadStatus() : ''\n  endif\n  let selection = s:Selection(a:visual ? 'v' : 'n')\n  if empty(selection)\n    return ''\n  endif\n  call filter(selection, 'v:val.section ==# selection[0].section')\n  let status = 0\n  let err = ''\n  try\n    for record in selection\n      if exists('*s:Do' . a:action . record.section)\n        let status = s:Do{a:action}{record.section}(record)\n      else\n        continue\n      endif\n      if !status\n        return ''\n      endif\n      let reload = reload || (status > 0)\n    endfor\n    if status < 0\n      execute record.lnum + 1\n    endif\n    let success = 1\n  catch /^fugitive:/\n    return 'echoerr ' . string(v:exception)\n  finally\n    if reload\n      execute s:ReloadStatus()\n    endif\n    if exists('success')\n      call s:StageReveal()\n    endif\n  endtry\n  return ''\nendfunction\n\nfunction! s:StageReveal() abort\n  exe 'normal! zv'\n  let begin = line('.')\n  if getline(begin) =~# '^@'\n    let end = begin + 1\n    while getline(end) =~# '^[ \\+-]'\n      let end += 1\n    endwhile\n  elseif getline(begin) =~# '^commit '\n    let end = begin\n    while end < line('$') && getline(end + 1) !~# '^commit '\n      let end += 1\n    endwhile\n  elseif getline(begin) =~# s:section_pattern\n    let end = begin\n    while len(getline(end + 1))\n      let end += 1\n    endwhile\n  endif\n  if exists('end')\n    while line('.') > line('w0') + &scrolloff && end > line('w$')\n      execute \"normal! \\<C-E>\"\n    endwhile\n  endif\nendfunction\n\nlet s:file_pattern = '^[A-Z?] .\\|^diff --'\nlet s:file_commit_pattern = s:file_pattern . '\\|^\\%(\\l\\{3,\\} \\)\\=[0-9a-f]\\{4,\\} '\nlet s:item_pattern = s:file_commit_pattern . '\\|^@@'\n\nfunction! s:NextHunk(count) abort\n  if &filetype ==# 'fugitive' && getline('.') =~# s:file_pattern\n    exe s:StageInline('show')\n  endif\n  for i in range(a:count)\n    if &filetype ==# 'fugitive'\n      call search(s:file_pattern . '\\|^@', 'W')\n      if getline('.') =~# s:file_pattern\n        exe s:StageInline('show')\n        if getline(line('.') + 1) =~# '^@'\n          +\n        endif\n      endif\n    else\n      call search('^@@', 'W')\n    endif\n  endfor\n  call s:StageReveal()\n  return '.'\nendfunction\n\nfunction! s:PreviousHunk(count) abort\n  normal! 0\n  for i in range(a:count)\n    if &filetype ==# 'fugitive'\n      if getline('.') =~# '^@' && getline(line('.') - 1) =~# s:file_pattern\n        -\n      endif\n      let lnum = search(s:file_pattern . '\\|^@','Wbn')\n      call s:StageInline('show', lnum)\n      call search('^? .\\|^@','Wb')\n    else\n      call search('^@@', 'Wb')\n    endif\n  endfor\n  call s:StageReveal()\n  return '.'\nendfunction\n\nfunction! s:NextFile(count) abort\n  for i in range(a:count)\n    exe s:StageInline('hide')\n    if !search(s:file_pattern, 'W')\n      break\n    endif\n  endfor\n  exe s:StageInline('hide')\n  return '.'\nendfunction\n\nfunction! s:PreviousFile(count) abort\n  exe s:StageInline('hide')\n  normal! 0\n  for i in range(a:count)\n    if !search(s:file_pattern, 'Wb')\n      break\n    endif\n    exe s:StageInline('hide')\n  endfor\n  return '.'\nendfunction\n\nfunction! s:NextItem(count) abort\n  for i in range(a:count)\n    if !search(s:item_pattern, 'W') && getline('.') !~# s:item_pattern\n      call search('^commit ', 'W')\n    endif\n  endfor\n  call s:StageReveal()\n  return '.'\nendfunction\n\nfunction! s:PreviousItem(count) abort\n  normal! 0\n  for i in range(a:count)\n    if !search(s:item_pattern, 'Wb') && getline('.') !~# s:item_pattern\n      call search('^commit ', 'Wb')\n    endif\n  endfor\n  call s:StageReveal()\n  return '.'\nendfunction\n\nlet s:section_pattern = '^[A-Z][a-z][^:]*$'\nlet s:section_commit_pattern = s:section_pattern . '\\|^commit '\n\nfunction! s:NextSection(count) abort\n  let orig = line('.')\n  if getline('.') !~# '^commit '\n    -\n  endif\n  for i in range(a:count)\n    if !search(s:section_commit_pattern, 'W')\n      break\n    endif\n  endfor\n  if getline('.') =~# s:section_commit_pattern\n    call s:StageReveal()\n    return getline('.') =~# s:section_pattern ? '+' : ':'\n  else\n    return orig\n  endif\nendfunction\n\nfunction! s:PreviousSection(count) abort\n  let orig = line('.')\n  if getline('.') !~# '^commit '\n    -\n  endif\n  normal! 0\n  for i in range(a:count)\n    if !search(s:section_commit_pattern . '\\|\\%^', 'bW')\n      break\n    endif\n  endfor\n  if getline('.') =~# s:section_commit_pattern || line('.') == 1\n    call s:StageReveal()\n    return getline('.') =~# s:section_pattern ? '+' : ':'\n  else\n    return orig\n  endif\nendfunction\n\nfunction! s:NextSectionEnd(count) abort\n  +\n  if empty(getline('.'))\n    +\n  endif\n  for i in range(a:count)\n    if !search(s:section_commit_pattern, 'W')\n      return '$'\n    endif\n  endfor\n  return search('^.', 'Wb')\nendfunction\n\nfunction! s:PreviousSectionEnd(count) abort\n  let old = line('.')\n  for i in range(a:count)\n    if search(s:section_commit_pattern, 'Wb') <= 1\n      exe old\n      if i\n        break\n      else\n        return ''\n      endif\n    endif\n    let old = line('.')\n  endfor\n  return search('^.', 'Wb')\nendfunction\n\nfunction! s:PatchSearchExpr(reverse) abort\n  let line = getline('.')\n  if col('.') ==# 1 && line =~# '^[+-]'\n    if line =~# '^[+-]\\{3\\} '\n      let pattern = '^[+-]\\{3\\} ' . substitute(escape(strpart(line, 4), '^$.*[]~\\'), '^\\w/', '\\\\w/', '') . '$'\n    else\n      let pattern = '^[+-]\\s*' . escape(substitute(strpart(line, 1), '^\\s*\\|\\s*$', '', ''), '^$.*[]~\\') . '\\s*$'\n    endif\n    if a:reverse\n      return '?' . escape(pattern, '/?') . \"\\<CR>\"\n    else\n      return '/' . escape(pattern, '/') . \"\\<CR>\"\n    endif\n  endif\n  return a:reverse ? '#' : '*'\nendfunction\n\nfunction! s:StageInlineGetDiff(diff_section, info) abort\n  let diff = []\n  if a:info.status ==# 'U'\n    let diff_header = 'diff --cc ' . s:Quote(a:info.relative[0])\n  else\n    let diff_header = 'diff --git ' . s:Quote(a:info.relative[-1]) . ' ' . s:Quote(a:info.relative[0])\n  endif\n  let stdout = fugitive#Wait(a:diff_section).stdout\n  let start = index(stdout, diff_header)\n  if start == -1\n    return [[], -1]\n  endif\n  let index = start + 1\n  while get(stdout, index, '@@') !~# '^@@\\|^diff '\n    let index += 1\n  endwhile\n  while get(stdout, index, '') =~# '^[@ \\+-]'\n    call add(diff, stdout[index])\n    let index += 1\n  endwhile\n  return [diff, start]\nendfunction\n\nfunction! s:StageInline(mode, ...) abort\n  if &filetype !=# 'fugitive'\n    return ''\n  endif\n  let lnum1 = a:0 ? a:1 : line('.')\n  let lnum = lnum1 + 1\n  if a:0 > 1 && a:2 == 0 && lnum1 == 1\n    let lnum = line('$') - 1\n  elseif a:0 > 1 && a:2 == 0\n    let info = s:StageInfo(lnum - 1)\n    if empty(info.paths) && len(info.section)\n      while len(getline(lnum))\n        let lnum += 1\n      endwhile\n    endif\n  elseif a:0 > 1\n    let lnum += a:2 - 1\n  endif\n  while lnum > lnum1\n    let lnum -= 1\n    while lnum > 0 && getline(lnum) =~# '^[ @\\+-]'\n      let lnum -= 1\n    endwhile\n    let info = s:StageInfo(lnum)\n    let diff_section = get(get(get(b:, 'fugitive_status', {}), 'diff', {}), info.section, {})\n    if empty(diff_section)\n      continue\n    endif\n    if getline(lnum + 1) =~# '^[ @\\+-]'\n      let lnum2 = lnum + 1\n      while getline(lnum2 + 1) =~# '^[ @\\+-]'\n        let lnum2 += 1\n      endwhile\n      if a:mode !=# 'show'\n        setlocal modifiable noreadonly\n        exe 'silent keepjumps ' . (lnum + 1) . ',' . lnum2 . 'delete _'\n        call remove(b:fugitive_expanded[info.section], info.filename)\n        setlocal nomodifiable readonly nomodified\n      endif\n      continue\n    endif\n    if info.status !~# '^[ADMRU]$' || a:mode ==# 'hide'\n      continue\n    endif\n    let [diff, start] = s:StageInlineGetDiff(diff_section, info)\n    if len(diff)\n      setlocal modifiable noreadonly\n      silent call append(lnum, diff)\n      let b:fugitive_expanded[info.section][info.filename] = [start]\n      setlocal nomodifiable readonly nomodified\n      if foldclosed(lnum+1) > 0\n        silent exe (lnum+1) . ',' . (lnum+len(diff)) . 'foldopen!'\n      endif\n    endif\n  endwhile\n  return lnum\nendfunction\n\nfunction! s:NextExpandedHunk(count) abort\n  for i in range(a:count)\n    call s:StageInline('show', line('.'), 1)\n    call search(s:file_pattern . '\\|^@','W')\n  endfor\n  return '.'\nendfunction\n\nfunction! s:StageDiff(diff) abort\n  let lnum = line('.')\n  let info = s:StageInfo(lnum)\n  let prefix = info.offset > 0 ? '+' . info.offset : ''\n  if info.submodule =~# '^S'\n    if info.section ==# 'Staged'\n      return 'Git --paginate diff --no-ext-diff --submodule=log --cached -- ' . info.paths[0]\n    elseif info.submodule =~# '^SC'\n      return 'Git --paginate diff --no-ext-diff --submodule=log -- ' . info.paths[0]\n    else\n      return 'Git --paginate diff --no-ext-diff --submodule=diff -- ' . info.paths[0]\n    endif\n  elseif empty(info.paths) && info.section ==# 'Staged'\n    return 'Git --paginate diff --no-ext-diff --cached'\n  elseif empty(info.paths)\n    return 'Git --paginate diff --no-ext-diff'\n  elseif len(info.paths) > 1\n    execute 'Gedit' . prefix s:fnameescape(':0:' . info.paths[0])\n    return 'keepalt ' . a:diff . '! @:'.s:fnameescape(info.paths[1])\n  elseif info.section ==# 'Staged' && info.sigil ==# '-'\n    execute 'Gedit' prefix s:fnameescape(':0:'.info.paths[0])\n    return 'keepalt ' . a:diff . '! :0:%'\n  elseif info.section ==# 'Staged'\n    execute 'Gedit' prefix s:fnameescape(':0:'.info.paths[0])\n    return 'keepalt ' . a:diff . '! @:%'\n  elseif info.sigil ==# '-'\n    execute 'Gedit' prefix s:fnameescape(':0:'.info.paths[0])\n    return 'keepalt ' . a:diff . '! :(top)%'\n  else\n    execute 'Gedit' prefix s:fnameescape(':(top)'.info.paths[0])\n    return 'keepalt ' . a:diff . '!'\n  endif\nendfunction\n\nfunction! s:StageDiffEdit() abort\n  let info = s:StageInfo(line('.'))\n  let arg = (empty(info.paths) ? s:Tree() : info.paths[0])\n  if info.section ==# 'Staged'\n    return 'Git --paginate diff --no-ext-diff --cached '.s:fnameescape(arg)\n  elseif info.status ==# '?'\n    call s:TreeChomp('add', '--intent-to-add', '--', arg)\n    return s:ReloadStatus()\n  else\n    return 'Git --paginate diff --no-ext-diff '.s:fnameescape(arg)\n  endif\nendfunction\n\nfunction! s:StageApply(info, reverse, extra) abort\n  if a:info.status ==# 'R'\n    throw 'fugitive: patching renamed file not yet supported'\n  endif\n  let cmd = ['apply', '-p0', '--recount'] + a:extra\n  let info = a:info\n  let start = info.patch\n  let end = info.lnum\n  let lines = getline(start, end)\n  if empty(filter(copy(lines), 'v:val =~# \"^[+-]\"'))\n    return -1\n  endif\n  while getline(end) =~# '^[-+\\ ]'\n    let end += 1\n    if getline(end) =~# '^[' . (a:reverse ? '+' : '-') . '\\ ]'\n      call add(lines, ' ' . getline(end)[1:-1])\n    endif\n  endwhile\n  while start > 0 && getline(start) !~# '^@'\n    let start -= 1\n    if getline(start) =~# '^[' . (a:reverse ? '+' : '-') . ' ]'\n      call insert(lines, ' ' . getline(start)[1:-1])\n    elseif getline(start) =~# '^@'\n      call insert(lines, getline(start))\n    endif\n  endwhile\n  if start == 0\n    throw 'fugitive: could not find hunk'\n  elseif getline(start) !~# '^@@ '\n    throw 'fugitive: cannot apply conflict hunk'\n  endif\n  let i = b:fugitive_expanded[info.section][info.filename][0]\n  let head = []\n  let diff_lines = fugitive#Wait(b:fugitive_status.diff[info.section]).stdout\n  while get(diff_lines, i, '@') !~# '^@'\n    let line = diff_lines[i]\n    if line ==# '--- /dev/null'\n      call add(head, '--- ' . get(diff_lines, i + 1, '')[4:-1])\n    elseif line !~# '^new file '\n      call add(head, line)\n    endif\n    let i += 1\n  endwhile\n  call extend(lines, head, 'keep')\n  let temp = tempname()\n  call writefile(lines, temp)\n  if a:reverse\n    call add(cmd, '--reverse')\n  endif\n  call extend(cmd, ['--', temp])\n  let output = s:ChompStderr(cmd)\n  if empty(output)\n    return 1\n  endif\n  call s:throw(output)\nendfunction\n\nfunction! s:StageDelete(lnum1, lnum2, count) abort\n  let restore = []\n\n  let err = ''\n  let did_conflict_err = 0\n  let reset_commit = matchstr(getline(a:lnum1), '^Un\\w\\+ \\%(to\\| from\\) \\zs\\S\\+')\n  try\n    for info in s:Selection(a:lnum1, a:lnum2)\n      if empty(info.paths)\n        if len(info.commit)\n          let reset_commit = info.commit . '^'\n        endif\n        continue\n      endif\n      let sub = get(s:StatusSectionFile(info.section, info.filename), 'submodule', '')\n      if sub =~# '^S' && info.status ==# 'M'\n        let undo = 'Git checkout ' . fugitive#RevParse('HEAD', FugitiveExtractGitDir(info.paths[0]))[0:10] . ' --'\n      elseif sub =~# '^S'\n        let err .= '|echoerr ' . string('fugitive: will not touch submodule ' . string(info.relative[0]))\n        break\n      elseif info.status ==# 'D'\n        let undo = 'GRemove'\n      elseif info.paths[0] =~# '/$'\n        let err .= '|echoerr ' . string('fugitive: will not delete directory ' . string(info.relative[0]))\n        break\n      else\n        let undo = 'Gread ' . s:TreeChomp('hash-object', '-w', '--', info.paths[0])[0:10]\n      endif\n      if info.patch\n        call s:StageApply(info, 1, info.section ==# 'Staged' ? ['--index'] : [])\n      elseif sub =~# '^S'\n        if info.section ==# 'Staged'\n          call s:TreeChomp('reset', '--', info.paths[0])\n        endif\n        call s:TreeChomp('submodule', 'update', '--', info.paths[0])\n      elseif info.status ==# '?'\n        call s:TreeChomp('clean', '-f', '--', info.paths[0])\n      elseif a:count == 2\n        if get(s:StatusSectionFile('Staged', info.filename), 'status', '') ==# 'D'\n          call delete(info.paths[0])\n        else\n          call s:TreeChomp('checkout', '--ours', '--', info.paths[0])\n        endif\n      elseif a:count == 3\n        if get(s:StatusSectionFile('Unstaged', info.filename), 'status', '') ==# 'D'\n          call delete(info.paths[0])\n        else\n          call s:TreeChomp('checkout', '--theirs', '--', info.paths[0])\n        endif\n      elseif info.status =~# '[ADU]' &&\n            \\ get(s:StatusSectionFile(info.section ==# 'Staged' ? 'Unstaged' : 'Staged', info.filename), 'status', '') =~# '[AU]'\n        if get(g:, 'fugitive_conflict_x', 0)\n          call s:TreeChomp('checkout', info.section ==# 'Unstaged' ? '--ours' : '--theirs', '--', info.paths[0])\n        else\n          if !did_conflict_err\n            let err .= '|echoerr \"Use 2X for --ours or 3X for --theirs\"'\n            let did_conflict_err = 1\n          endif\n          continue\n        endif\n      elseif info.status ==# 'U'\n        call delete(info.paths[0])\n      elseif info.status ==# 'A'\n        call s:TreeChomp('rm', '-f', '--', info.paths[0])\n      elseif info.section ==# 'Unstaged'\n        call s:TreeChomp('checkout', '--', info.paths[0])\n      else\n        call s:TreeChomp('checkout', '@', '--', info.paths[0])\n      endif\n      if len(undo)\n        call add(restore, ':Gsplit ' . s:fnameescape(info.relative[0]) . '|' . undo)\n      endif\n    endfor\n  catch /^fugitive:/\n    let err .= '|echoerr ' . string(v:exception)\n  endtry\n  if empty(restore)\n    if len(reset_commit) && empty(err)\n      call feedkeys(':Git reset ' . reset_commit)\n    endif\n    return err[1:-1]\n  endif\n  exe s:ReloadStatus()\n  call s:StageReveal()\n  return 'checktime|redraw|echomsg ' . string('To restore, ' . join(restore, '|')) . err\nendfunction\n\nfunction! s:StageIgnore(lnum1, lnum2, count) abort\n  let paths = []\n  for info in s:Selection(a:lnum1, a:lnum2)\n    call extend(paths, info.relative)\n  endfor\n  call map(paths, '\"/\" . v:val')\n  if !a:0\n    let dir = fugitive#Find('.git/info/')\n    if !isdirectory(dir)\n      try\n        call mkdir(dir)\n      catch\n      endtry\n    endif\n  endif\n  exe 'Gsplit' (a:count ? '.gitignore' : '.git/info/exclude')\n  let last = line('$')\n  if last == 1 && empty(getline(1))\n    call setline(last, paths)\n  else\n    call append(last, paths)\n    exe last + 1\n  endif\n  return ''\nendfunction\n\nfunction! s:DoToggleHeadHeader(value) abort\n  exe 'edit' fnameescape(fugitive#Find('.git/'))\n  call search('\\C^index$', 'wc')\nendfunction\n\nfunction! s:DoToggleHelpHeader(value) abort\n  exe 'help fugitive-maps'\nendfunction\n\nfunction! s:DoStagePushHeader(value) abort\n  let stat = get(b:, 'fugitive_status', {})\n  let remote = get(stat, 'push_remote', '')\n  let branch = substitute(get(stat, 'push', ''), '^ref/heads/', '', '')\n  if empty(remote) || empty(branch)\n    return\n  endif\n  call feedkeys(':Git push ' . remote . ' ' . branch)\nendfunction\n\nfunction! s:DoTogglePushHeader(value) abort\n  return s:DoStagePushHeader(a:value)\nendfunction\n\nfunction! s:DoStageUnpushedHeading(heading) abort\n  let stat = get(b:, 'fugitive_status', {})\n  let remote = get(stat, 'push_remote', '')\n  let push = get(stat, 'push', '')\n  if empty(remote) || empty(push)\n    return\n  endif\n  call feedkeys(':Git push ' . remote . ' ' . '@:' . push)\nendfunction\n\nfunction! s:DoToggleUnpushedHeading(heading) abort\n  return s:DoStageUnpushedHeading(a:heading)\nendfunction\n\nfunction! s:DoStageUnpushed(record) abort\n  let stat = get(b:, 'fugitive_status', {})\n  let remote = get(stat, 'push_remote', '')\n  let push = get(stat, 'push', '')\n  if empty(remote) || empty(push)\n    return\n  endif\n  call feedkeys(':Git push ' . remote . ' ' . a:record.commit . ':' . push)\nendfunction\n\nfunction! s:DoToggleUnpushed(record) abort\n  return s:DoStageUnpushed(a:record)\nendfunction\n\nfunction! s:DoUnstageUnpulledHeading(heading) abort\n  call feedkeys(':Git rebase')\nendfunction\n\nfunction! s:DoToggleUnpulledHeading(heading) abort\n  call s:DoUnstageUnpulledHeading(a:heading)\nendfunction\n\nfunction! s:DoUnstageUnpulled(record) abort\n  call feedkeys(':Git rebase ' . a:record.commit)\nendfunction\n\nfunction! s:DoToggleUnpulled(record) abort\n  call s:DoUnstageUnpulled(a:record)\nendfunction\n\nfunction! s:DoUnstageUnpushed(record) abort\n  call feedkeys(':Git -c sequence.editor=true rebase --interactive --autosquash ' . a:record.commit . '^')\nendfunction\n\nfunction! s:DoToggleStagedHeading(...) abort\n  call s:TreeChomp('reset', '-q')\n  return 1\nendfunction\n\nfunction! s:DoUnstageStagedHeading(heading) abort\n  return s:DoToggleStagedHeading(a:heading)\nendfunction\n\nfunction! s:DoToggleUnstagedHeading(...) abort\n  call s:TreeChomp('add', '-u')\n  return 1\nendfunction\n\nfunction! s:DoStageUnstagedHeading(heading) abort\n  return s:DoToggleUnstagedHeading(a:heading)\nendfunction\n\nfunction! s:DoToggleUntrackedHeading(...) abort\n  call s:TreeChomp('add', '.')\n  return 1\nendfunction\n\nfunction! s:DoStageUntrackedHeading(heading) abort\n  return s:DoToggleUntrackedHeading(a:heading)\nendfunction\n\nfunction! s:DoToggleStaged(record) abort\n  if a:record.patch\n    return s:StageApply(a:record, 1, ['--cached'])\n  else\n    call s:TreeChomp(['reset', '-q', '--'] + a:record.paths)\n    return 1\n  endif\nendfunction\n\nfunction! s:DoUnstageStaged(record) abort\n  return s:DoToggleStaged(a:record)\nendfunction\n\nfunction! s:DoToggleUnstaged(record) abort\n  if a:record.patch\n    return s:StageApply(a:record, 0, ['--cached'])\n  else\n    call s:TreeChomp(['add', '-A', '--'] + a:record.paths)\n    return 1\n  endif\nendfunction\n\nfunction! s:DoStageUnstaged(record) abort\n  return s:DoToggleUnstaged(a:record)\nendfunction\n\nfunction! s:DoUnstageUnstaged(record) abort\n  if a:record.status ==# 'A'\n    call s:TreeChomp(['reset', '-q', '--'] + a:record.paths)\n    return 1\n  else\n    return -1\n  endif\nendfunction\n\nfunction! s:DoToggleUntracked(record) abort\n  call s:TreeChomp(['add', '--'] + a:record.paths)\n  return 1\nendfunction\n\nfunction! s:DoStageUntracked(record) abort\n  return s:DoToggleUntracked(a:record)\nendfunction\n\nfunction! s:StagePatch(lnum1, lnum2, ...) abort\n  let add = []\n  let reset = []\n  let intend = []\n  let patch_only = a:0 && a:1\n\n  for lnum in range(a:lnum1,a:lnum2)\n    let info = s:StageInfo(lnum)\n    if empty(info.paths) && info.section ==# 'Staged'\n      execute 'tab Git reset --patch'\n      break\n    elseif empty(info.paths) && info.section ==# 'Unstaged'\n      execute 'tab Git add --patch'\n      break\n    elseif empty(info.paths) && info.section ==# 'Untracked'\n      execute 'tab Git add --interactive'\n      break\n    elseif !patch_only && info.section ==# 'Unpushed'\n      if empty(info.commit)\n        call s:DoStageUnpushedHeading(info)\n      else\n        call s:DoStageUnpushed(info)\n      endif\n      return ''\n    elseif empty(info.paths)\n      continue\n    endif\n    execute lnum\n    if info.section ==# 'Staged'\n      let reset += info.relative\n    elseif info.section ==# 'Untracked'\n      let intend += info.paths\n    elseif info.status !~# '^D'\n      let add += info.relative\n    endif\n  endfor\n  try\n    if !empty(intend)\n      call s:TreeChomp(['add', '--intent-to-add', '--'] + intend)\n    endif\n    if !empty(add)\n      execute \"tab Git add --patch -- \".join(map(add,'fnameescape(v:val)'))\n    endif\n    if !empty(reset)\n      execute \"tab Git reset --patch -- \".join(map(reset,'fnameescape(v:val)'))\n    endif\n  catch /^fugitive:/\n    return 'echoerr ' . string(v:exception)\n  endtry\n  return s:ReloadStatus()\nendfunction\n\n\" Section: :Git commit, :Git revert\n\nfunction! s:CommitInteractive(line1, line2, range, bang, mods, options, patch) abort\n  let status = s:StatusCommand(a:line1, a:line2, a:range, get(a:options, 'curwin') && a:line2 < 0 ? 0 : a:line2, a:bang, a:mods, '', '', [], a:options)\n  let status = len(status) ? status . '|' : ''\n  if a:patch\n    return status . 'if search(\"^Unstaged\")|exe \"normal >\"|exe \"+\"|endif'\n  else\n    return status . 'if search(\"^Untracked\\\\|^Unstaged\")|exe \"+\"|endif'\n  endif\nendfunction\n\nfunction! s:CommitSubcommand(line1, line2, range, bang, mods, options) abort\n  let argv = copy(a:options.subcommand_args)\n  let i = 0\n  while get(argv, i, '--') !=# '--'\n    if argv[i] =~# '^-[apzsneiovq].'\n      call insert(argv, argv[i][0:1])\n      let argv[i+1] = '-' . argv[i+1][2:-1]\n    else\n      let i += 1\n    endif\n  endwhile\n  if s:HasOpt(argv, '-i', '--interactive')\n    return s:CommitInteractive(a:line1, a:line2, a:range, a:bang, a:mods, a:options, 0)\n  elseif s:HasOpt(argv, '-p', '--patch')\n    return s:CommitInteractive(a:line1, a:line2, a:range, a:bang, a:mods, a:options, 1)\n  else\n    return {}\n  endif\nendfunction\n\nfunction! s:RevertSubcommand(line1, line2, range, bang, mods, options) abort\n  return {'insert_args': ['--edit']}\nendfunction\n\nfunction! fugitive#CommitComplete(A, L, P, ...) abort\n  let dir = a:0 ? a:1 : s:Dir()\n  if a:A =~# '^--fixup=\\|^--squash='\n    let commits = s:LinesError([dir, 'log', '--pretty=format:%s', '@{upstream}..'])[0]\n    let pre = matchstr(a:A, '^--\\w*=''\\=') . ':/^'\n    if pre =~# \"'\"\n      call map(commits, 'pre . string(tr(v:val, \"|\\\"^$*[]\", \".......\"))[1:-1]')\n      call filter(commits, 'strpart(v:val, 0, strlen(a:A)) ==# a:A')\n      return commits\n    else\n      return s:FilterEscape(map(commits, 'pre . tr(v:val, \"\\\\ !^$*?[]()''\\\"`&;<>|#\", \"....................\")'), a:A)\n    endif\n  else\n    return s:CompleteSub('commit', a:A, a:L, a:P, function('fugitive#CompletePath'), a:000)\n  endif\n  return []\nendfunction\n\nfunction! fugitive#RevertComplete(A, L, P, ...) abort\n  return s:CompleteSub('revert', a:A, a:L, a:P, function('s:CompleteRevision'), a:000)\nendfunction\n\n\" Section: :Git merge, :Git rebase, :Git pull\n\nfunction! fugitive#MergeComplete(A, L, P, ...) abort\n  return s:CompleteSub('merge', a:A, a:L, a:P, function('s:CompleteRevision'), a:000)\nendfunction\n\nfunction! fugitive#RebaseComplete(A, L, P, ...) abort\n  return s:CompleteSub('rebase', a:A, a:L, a:P, function('s:CompleteRevision'), a:000)\nendfunction\n\nfunction! fugitive#PullComplete(A, L, P, ...) abort\n  return s:CompleteSub('pull', a:A, a:L, a:P, function('s:CompleteRemote'), a:000)\nendfunction\n\nfunction! s:MergeSubcommand(line1, line2, range, bang, mods, options) abort\n  if empty(a:options.subcommand_args) && (\n        \\ filereadable(fugitive#Find('.git/MERGE_MSG', a:options)) ||\n        \\ isdirectory(fugitive#Find('.git/rebase-apply', a:options)) ||\n        \\  !empty(s:TreeChomp([a:options.git_dir, 'diff-files', '--diff-filter=U'])))\n    return 'echoerr \":Git merge for loading conflicts has been removed in favor of :Git mergetool\"'\n  endif\n  return {}\nendfunction\n\nfunction! s:RebaseSubcommand(line1, line2, range, bang, mods, options) abort\n  let args = a:options.subcommand_args\n  if s:HasOpt(args, '--autosquash') && !s:HasOpt(args, '-i', '--interactive')\n    return {'env': {'GIT_SEQUENCE_EDITOR': 'true'}, 'insert_args': ['--interactive']}\n  endif\n  return {}\nendfunction\n\n\" Section: :Git bisect\n\nfunction! s:CompleteBisect(A, L, P, ...) abort\n  let bisect_subcmd = matchstr(a:L, '\\u\\w*[! ] *.\\{-\\}\\s\\@<=\\zs[^-[:space:]]\\S*\\ze ')\n  if empty(bisect_subcmd)\n    let subcmds = ['start', 'bad', 'new', 'good', 'old', 'terms', 'skip', 'next', 'reset', 'replay', 'log', 'run']\n    return s:FilterEscape(subcmds, a:A)\n  endif\n  let dir = a:0 ? a:1 : s:Dir()\n  return fugitive#CompleteObject(a:A, dir)\nendfunction\n\nfunction! fugitive#BisectComplete(A, L, P, ...) abort\n  return s:CompleteSub('bisect', a:A, a:L, a:P, function('s:CompleteBisect'), a:000)\nendfunction\n\n\" Section: :Git difftool, :Git mergetool\n\nfunction! s:ToolItems(state, from, to, offsets, text, ...) abort\n  let items = []\n  for i in range(len(a:state.diff))\n    let diff = a:state.diff[i]\n    let path = (i == len(a:state.diff) - 1) ? a:to : a:from\n    if empty(path)\n      return []\n    endif\n    let item = {\n          \\ 'valid': a:0 ? a:1 : 1,\n          \\ 'filename': diff.filename . s:VimSlash(path),\n          \\ 'lnum': matchstr(get(a:offsets, i), '\\d\\+'),\n          \\ 'text': a:text}\n    if len(get(diff, 'module', ''))\n      let item.module = diff.module . path\n    endif\n    call add(items, item)\n  endfor\n  if get(a:offsets, 0, '') isnot# 'none'\n    let items[-1].context = {'diff': items[0:-2]}\n  endif\n  return [items[-1]]\nendfunction\n\nfunction! s:ToolToFrom(str) abort\n  if a:str =~# ' => '\n    let str = a:str =~# '{.* => .*}' ? a:str : '{' . a:str . '}'\n    return [substitute(str, '{.* => \\(.*\\)}', '\\1', ''),\n          \\ substitute(str, '{\\(.*\\) => .*}', '\\1', '')]\n  else\n    return [a:str, a:str]\n  endif\nendfunction\n\nfunction! s:ToolParse(state, line) abort\n  if type(a:line) !=# type('') || a:state.mode ==# 'hunk' && a:line =~# '^[ +-]'\n    return []\n  elseif a:line =~# '^diff '\n    let a:state.mode = 'diffhead'\n    let a:state.from = ''\n    let a:state.to = ''\n  elseif a:state.mode ==# 'diffhead' && a:line =~# '^--- [^/]'\n    let a:state.from = a:line[4:-1]\n    let a:state.to = a:state.from\n  elseif a:state.mode ==# 'diffhead' && a:line =~# '^+++ [^/]'\n    let a:state.to = a:line[4:-1]\n    if empty(get(a:state, 'from', ''))\n      let a:state.from = a:state.to\n    endif\n  elseif a:line[0] ==# '@'\n    let a:state.mode = 'hunk'\n    if has_key(a:state, 'from')\n      let offsets = split(matchstr(a:line, '^@\\+ \\zs[-+0-9, ]\\+\\ze @'), ' ')\n      return s:ToolItems(a:state, a:state.from, a:state.to, offsets, matchstr(a:line, ' @@\\+ \\zs.*'))\n    endif\n  elseif a:line =~# '^\\* Unmerged path .'\n    let file = a:line[16:-1]\n    return s:ToolItems(a:state, file, file, [], '')\n  elseif a:line =~# '^[A-Z]\\d*\\t.\\|^:.*\\t.'\n    \" --raw, --name-status\n    let [status; files] = split(a:line, \"\\t\")\n    return s:ToolItems(a:state, files[0], files[-1], [], a:state.name_only ? '' : status)\n  elseif a:line =~# '^ \\S.* |'\n    \" --stat\n    let [_, to, changes; __] = matchlist(a:line, '^ \\(.\\{-\\}\\) \\+|\\zs \\(.*\\)$')\n    let [to, from] = s:ToolToFrom(to)\n    return s:ToolItems(a:state, from, to, [], changes)\n  elseif a:line =~# '^ *\\([0-9.]\\+%\\) .'\n    \" --dirstat\n    let [_, changes, to; __] = matchlist(a:line, '^ *\\([0-9.]\\+%\\) \\(.*\\)')\n    return s:ToolItems(a:state, to, to, [], changes)\n  elseif a:line =~# '^\\(\\d\\+\\|-\\)\\t\\(\\d\\+\\|-\\)\\t.'\n    \" --numstat\n    let [_, add, remove, to; __] = matchlist(a:line, '^\\(\\d\\+\\|-\\)\\t\\(\\d\\+\\|-\\)\\t\\(.*\\)')\n    let [to, from] = s:ToolToFrom(to)\n    return s:ToolItems(a:state, from, to, [], add ==# '-' ? 'Binary file' : '+' . add . ' -' . remove, add !=# '-')\n  elseif a:line =~# '^\\f\\+:\\d\\+: \\D'\n    \" --check\n    let [_, to, line, text; __] = matchlist(a:line, '^\\(\\f\\+\\):\\(\\d\\+\\):\\s*\\(.*\\)$')\n    return s:ToolItems(a:state, to, to, ['none', line], text)\n  elseif a:state.mode !=# 'diffhead' && a:state.mode !=# 'hunk' && len(a:line) || a:line =~# '^git: \\|^usage: \\|^error: \\|^fatal: '\n    return [{'text': a:line}]\n  endif\n  return []\nendfunction\n\nfunction! s:ToolStream(line1, line2, range, bang, mods, options, args, state) abort\n  let i = 0\n  let argv = copy(a:args)\n  let prompt = 1\n  let state = a:state\n  while i < len(argv)\n    let match = matchlist(argv[i], '^\\(-[a-zABDFH-KN-RT-Z]\\)\\ze\\(.*\\)')\n    if len(match) && len(match[2])\n      call insert(argv, match[1])\n      let argv[i+1] = '-' . match[2]\n      continue\n    endif\n    let arg = argv[i]\n    if arg =~# '^-t$\\|^--tool=\\|^--tool-help$\\|^--help$'\n      return {}\n    elseif arg =~# '^-y$\\|^--no-prompt$'\n      let prompt = 0\n      call remove(argv, i)\n      continue\n    elseif arg ==# '--prompt'\n      let prompt = 1\n      call remove(argv, i)\n      continue\n    elseif arg =~# '^--\\%(no-\\)\\=\\(symlinks\\|trust-exit-code\\|gui\\)$'\n      call remove(argv, i)\n      continue\n    elseif arg ==# '--'\n      break\n    endif\n    let i += 1\n  endwhile\n  call fugitive#Autowrite()\n  let a:state.mode = 'init'\n  let a:state.from = ''\n  let a:state.to = ''\n  let exec = s:UserCommandList({'git': a:options.git, 'git_dir': a:options.git_dir}) + ['-c', 'diff.context=0']\n  let exec += a:options.flags + ['--no-pager', 'diff', '--no-ext-diff', '--no-color', '--no-prefix'] + argv\n  if prompt\n    let title = ':Git ' . s:fnameescape(a:options.flags + [a:options.subcommand] + a:options.subcommand_args)\n    return s:QuickfixStream(get(a:options, 'curwin') && a:line2 < 0 ? 0 : a:line2, 'difftool', title, exec, !a:bang, a:mods, s:function('s:ToolParse'), a:state)\n  else\n    let filename = ''\n    let cmd = []\n    let tabnr = tabpagenr() + 1\n    for line in s:SystemList(exec)[0]\n      for item in s:ToolParse(a:state, line)\n        if len(get(item, 'filename', '')) && item.filename != filename\n          call add(cmd, 'tabedit ' . s:fnameescape(item.filename))\n          for i in reverse(range(len(get(get(item, 'context', {}), 'diff', []))))\n            call add(cmd, (i ? 'rightbelow' : 'leftabove') . ' vertical Gdiffsplit! ' . s:fnameescape(item.context.diff[i].filename))\n          endfor\n          call add(cmd, 'wincmd =')\n          let filename = item.filename\n        endif\n      endfor\n    endfor\n    return join(cmd, '|') . (empty(cmd) ? '' : '|' . tabnr . 'tabnext')\n  endif\nendfunction\n\nfunction! s:MergetoolSubcommand(line1, line2, range, bang, mods, options) abort\n  let dir = a:options.git_dir\n  exe s:DirCheck(dir)\n  let i = 0\n  let prompt = 1\n  let cmd = ['diff', '--diff-filter=U']\n  let state = {'name_only': 0}\n  let state.diff = [{'prefix': ':2:', 'module': ':2:'}, {'prefix': ':3:', 'module': ':3:'}, {'prefix': ':(top)'}]\n  call map(state.diff, 'extend(v:val, {\"filename\": fugitive#Find(v:val.prefix, dir)})')\n  return s:ToolStream(a:line1, a:line2, a:range, a:bang, a:mods, a:options, ['--diff-filter=U'] + a:options.subcommand_args, state)\nendfunction\n\nfunction! s:DifftoolSubcommand(line1, line2, range, bang, mods, options) abort\n  let dir = s:Dir(a:options)\n  exe s:DirCheck(dir)\n  let i = 0\n  let argv = copy(a:options.subcommand_args)\n  let commits = []\n  let cached = 0\n  let reverse = 1\n  let prompt = 1\n  let state = {'name_only': 0}\n  let merge_base_against = {}\n  let dash = (index(argv, '--') > i ? ['--'] : [])\n  while i < len(argv)\n    let match = matchlist(argv[i], '^\\(-[a-zABDFH-KN-RT-Z]\\)\\ze\\(.*\\)')\n    if len(match) && len(match[2])\n      call insert(argv, match[1])\n      let argv[i+1] = '-' . match[2]\n      continue\n    endif\n    let arg = argv[i]\n    if arg ==# '--cached'\n      let cached = 1\n    elseif arg ==# '-R'\n      let reverse = 1\n    elseif arg ==# '--name-only'\n      let state.name_only = 1\n      let argv[0] = '--name-status'\n    elseif arg ==# '--'\n      break\n    elseif arg !~# '^-\\|^\\.\\.\\=\\%(/\\|$\\)'\n      let parsed = s:LinesError(['rev-parse', '--revs-only', substitute(arg, ':.*', '', '')] + dash)[0]\n      call map(parsed, '{\"uninteresting\": v:val =~# \"^\\\\^\", \"prefix\": substitute(v:val, \"^\\\\^\", \"\", \"\") . \":\"}')\n      let merge_base_against = {}\n      if arg =~# '\\.\\.\\.' && len(parsed) > 2\n        let display = map(split(arg, '\\.\\.\\.', 1), 'empty(v:val) ? \"@\" : v:val')\n        if len(display) == 2\n          let parsed[0].module = display[1] . ':'\n          let parsed[1].module = display[0] . ':'\n        endif\n        let parsed[2].module = arg . ':'\n        if empty(commits)\n          let merge_base_against = parsed[0]\n          let parsed = [parsed[2]]\n        endif\n      elseif arg =~# '\\.\\.' && len(parsed) == 2\n        let display = map(split(arg, '\\.\\.', 1), 'empty(v:val) ? \"@\" : v:val')\n        if len(display) == 2\n          let parsed[0].module = display[0] . ':'\n          let parsed[1].module = display[1] . ':'\n        endif\n      elseif len(parsed) == 1\n        let parsed[0].module = arg . ':'\n      endif\n      call extend(commits, parsed)\n    endif\n    let i += 1\n  endwhile\n  if len(merge_base_against)\n    call add(commits, merge_base_against)\n  endif\n  let commits = filter(copy(commits), 'v:val.uninteresting') + filter(commits, '!v:val.uninteresting')\n  if cached\n    if empty(commits)\n      call add(commits, {'prefix': '@:', 'module': '@:'})\n    endif\n    call add(commits, {'prefix': ':0:', 'module': ':0:'})\n  elseif len(commits) < 2\n    call add(commits, {'prefix': ':(top)'})\n    if len(commits) < 2\n      call insert(commits, {'prefix': ':0:', 'module': ':0:'})\n    endif\n  endif\n  if reverse\n    let commits = [commits[-1]] + repeat([commits[0]], len(commits) - 1)\n    call reverse(commits)\n  endif\n  if len(commits) > 2\n    call add(commits, remove(commits, 0))\n  endif\n  call map(commits, 'extend(v:val, {\"filename\": fugitive#Find(v:val.prefix, dir)})')\n  let state.diff = commits\n  return s:ToolStream(a:line1, a:line2, a:range, a:bang, a:mods, a:options, argv, state)\nendfunction\n\n\" Section: :Ggrep, :Glog\n\nif !exists('g:fugitive_summary_format')\n  let g:fugitive_summary_format = '%s'\nendif\n\nfunction! fugitive#GrepComplete(A, L, P) abort\n  return s:CompleteSub('grep', a:A, a:L, a:P)\nendfunction\n\nfunction! fugitive#LogComplete(A, L, P) abort\n  return s:CompleteSub('log', a:A, a:L, a:P)\nendfunction\n\nfunction! s:GrepParseLine(options, quiet, dir, line) abort\n  if !a:quiet\n    echo a:line\n  endif\n  let entry = {'valid': 1}\n  let match = matchlist(a:line, '^\\(.\\{-\\}\\):\\([1-9]\\d*\\):\\([1-9]\\d*:\\)\\=\\(.*\\)$')\n  if a:line =~# '^git: \\|^usage: \\|^error: \\|^fatal: \\|^BUG: '\n    return {'text': a:line}\n  elseif len(match)\n    let entry.module = match[1]\n    let entry.lnum = +match[2]\n    let entry.col = +match[3]\n    let entry.text = match[4]\n  else\n    let entry.module = matchstr(a:line, '\\CBinary file \\zs.*\\ze matches$')\n    if len(entry.module)\n      let entry.text = 'Binary file'\n      let entry.valid = 0\n    endif\n  endif\n  if empty(entry.module) && !a:options.line_number\n    let match = matchlist(a:line, '^\\(.\\{-\\}\\):\\(.*\\)$')\n    if len(match)\n      let entry.module = match[1]\n      let entry.pattern = '\\M^' . escape(match[2], '\\.^$/') . '$'\n    endif\n  endif\n  if empty(entry.module) && a:options.name_count && a:line =~# ':\\d\\+$'\n    let entry.text = matchstr(a:line, '\\d\\+$')\n    let entry.module = strpart(a:line, 0, len(a:line) - len(entry.text) - 1)\n  endif\n  if empty(entry.module) && a:options.name_only\n    let entry.module = a:line\n  endif\n  if empty(entry.module)\n    return {'text': a:line}\n  endif\n  if entry.module !~# ':'\n    let entry.filename = s:PathJoin(a:options.prefix, entry.module)\n  else\n    let entry.filename = fugitive#Find(matchstr(entry.module, '^[^:]*:') .\n          \\ substitute(matchstr(entry.module, ':\\zs.*'), '/\\=:', '/', 'g'), a:dir)\n  endif\n  return entry\nendfunction\n\nlet s:grep_combine_flags = '[aiIrhHEGPFnlLzocpWq]\\{-\\}'\nfunction! s:GrepOptions(args, dir) abort\n  let options = {'name_only': 0, 'name_count': 0, 'line_number': 0}\n  let tree = s:Tree(a:dir)\n  let prefix = empty(tree) ? fugitive#Find(':0:', a:dir) :\n        \\ s:VimSlash(tree . '/')\n  let options.prefix = prefix\n  for arg in a:args\n    if arg ==# '--'\n      break\n    endif\n    if arg =~# '^\\%(-' . s:grep_combine_flags . 'c\\|--count\\)$'\n      let options.name_count = 1\n    endif\n    if arg =~# '^\\%(-' . s:grep_combine_flags . 'n\\|--line-number\\)$'\n      let options.line_number = 1\n    elseif arg =~# '^\\%(--no-line-number\\)$'\n      let options.line_number = 0\n    endif\n    if arg =~# '^\\%(-' . s:grep_combine_flags . '[lL]\\|--files-with-matches\\|--name-only\\|--files-without-match\\)$'\n      let options.name_only = 1\n    endif\n    if arg ==# '--cached'\n      let options.prefix = fugitive#Find(':0:', a:dir)\n    elseif arg ==# '--no-cached'\n      let options.prefix = prefix\n    endif\n  endfor\n  return options\nendfunction\n\nfunction! s:GrepCfile(result) abort\n  let options = s:GrepOptions(a:result.args, a:result)\n  let entry = s:GrepParseLine(options, 1, a:result, getline('.'))\n  if get(entry, 'col')\n    return [entry.filename, entry.lnum, \"norm!\" . entry.col . \"|\"]\n  elseif has_key(entry, 'lnum')\n    return [entry.filename, entry.lnum]\n  elseif has_key(entry, 'pattern')\n    return [entry.filename, '', 'silent /' . entry.pattern]\n  elseif has_key(entry, 'filename')\n    return [entry.filename]\n  else\n    return []\n  endif\nendfunction\n\nfunction! s:GrepSubcommand(line1, line2, range, bang, mods, options) abort\n  let args = copy(a:options.subcommand_args)\n  let handle = -1\n  let quiet = 0\n  let i = 0\n  while i < len(args) && args[i] !=# '--'\n    let partition = matchstr(args[i], '^-' . s:grep_combine_flags . '\\ze[qzO]')\n    if len(partition) > 1\n      call insert(args, '-' . strpart(args[i], len(partition)), i+1)\n      let args[i] = partition\n    elseif args[i] =~# '^\\%(-' . s:grep_combine_flags . '[eABC]\\|--max-depth\\|--context\\|--after-context\\|--before-context\\|--threads\\)$'\n      let i += 1\n    elseif args[i] =~# '^\\%(-O\\|--open-files-in-pager\\)$'\n      let handle = 1\n      call remove(args, i)\n      continue\n    elseif args[i] =~# '^\\%(-O\\|--open-files-in-pager=\\)'\n      let handle = 0\n    elseif args[i] =~# '^-[qz].'\n      let args[i] = '-' . args[i][2:-1]\n      let quiet = 1\n    elseif args[i] =~# '^\\%(-[qz]\\|--quiet\\)$'\n      let quiet = 1\n      call remove(args, i)\n      continue\n    elseif args[i] =~# '^--no-quiet$'\n      let quiet = 0\n    elseif args[i] =~# '^\\%(--heading\\)$'\n      call remove(args, i)\n      continue\n    endif\n    let i += 1\n  endwhile\n  if handle < 0 ? !quiet : !handle\n    return {}\n  endif\n  call fugitive#Autowrite()\n  let listnr = get(a:options, 'curwin') && a:line2 < 0 ? 0 : a:line2\n  if s:HasOpt(args, '--no-line-number')\n    let lc = []\n  else\n    let lc = fugitive#GitVersion(2, 19) ? ['-n', '--column'] : ['-n']\n  endif\n  let cmd = ['grep', '--no-color', '--full-name'] + lc\n  let dir = s:Dir(a:options)\n  let options = s:GrepOptions(lc + args, dir)\n  if listnr > 0\n    exe listnr 'wincmd w'\n  else\n    call s:BlurStatus()\n  endif\n  let title = (listnr < 0 ? ':Ggrep ' : ':Glgrep ') . s:fnameescape(args)\n  call s:QuickfixCreate(listnr, {'title': title})\n  let tempfile = tempname()\n  let state = {\n        \\ 'git': a:options.git,\n        \\ 'flags': a:options.flags,\n        \\ 'args': cmd + args,\n        \\ 'git_dir': s:GitDir(a:options),\n        \\ 'cwd': s:UserCommandCwd(a:options),\n        \\ 'filetype': 'git',\n        \\ 'mods': s:Mods(a:mods),\n        \\ 'file': s:Resolve(tempfile)}\n  let event = listnr < 0 ? 'grep-fugitive' : 'lgrep-fugitive'\n  exe s:DoAutocmd('QuickFixCmdPre ' . event)\n  try\n    if !quiet && &more\n      let more = 1\n      set nomore\n    endif\n    if !quiet\n      echo title\n    endif\n    let list = s:SystemList(s:UserCommandList(a:options) + cmd + args)[0]\n    call writefile(list + [''], tempfile, 'b')\n    call s:RunSave(state)\n    call map(list, 's:GrepParseLine(options, ' . quiet . ', dir, v:val)')\n    call s:QuickfixSet(listnr, list, 'a')\n    let press_enter_shortfall = &cmdheight - len(list)\n    if press_enter_shortfall > 0 && !quiet\n      echo repeat(\"\\n\", press_enter_shortfall - 1)\n    endif\n  finally\n    if exists('l:more')\n      let &more = more\n    endif\n  endtry\n  call s:RunFinished(state)\n  exe s:DoAutocmd('QuickFixCmdPost ' . event)\n  if quiet\n    let bufnr = bufnr('')\n    exe s:QuickfixOpen(listnr, a:mods)\n    if bufnr != bufnr('') && !a:bang\n      wincmd p\n    endif\n  end\n  if !a:bang && !empty(list)\n    return 'silent ' . (listnr < 0 ? 'c' : 'l').'first'\n  else\n    return ''\n  endif\nendfunction\n\nfunction! fugitive#GrepCommand(line1, line2, range, bang, mods, arg) abort\n  return fugitive#Command(a:line1, a:line2, a:range, a:bang, a:mods,\n        \\ \"grep -O \" . a:arg)\nendfunction\n\nlet s:log_diff_context = '{\"filename\": fugitive#Find(v:val . from, a:dir), \"lnum\": get(offsets, v:key), \"module\": strpart(v:val, 0, len(a:state.base_module)) . from}'\n\nfunction! s:LogFlushQueue(state, dir) abort\n  let queue = remove(a:state, 'queue')\n  if a:state.child_found && get(a:state, 'ignore_commit')\n    call remove(queue, 0)\n  elseif len(queue) && len(a:state.target) && len(get(a:state, 'parents', []))\n    let from = substitute(a:state.target, '^/', ':', '')\n    let offsets = []\n    let queue[0].context.diff = map(copy(a:state.parents), s:log_diff_context)\n  endif\n  if len(queue) && queue[-1] ==# {'text': ''}\n    call remove(queue, -1)\n  endif\n  return queue\nendfunction\n\nfunction! s:LogParse(state, dir, prefix, line) abort\n  if a:state.mode ==# 'hunk' && a:line =~# '^[-+ ]'\n    return []\n  endif\n  let list = matchlist(a:line, '^\\%(fugitive \\(.\\{-\\}\\)\\t\\|commit \\|From \\)\\=\\(\\x\\{40,\\}\\)\\%( \\(.*\\)\\)\\=$')\n  if len(list)\n    let queue = s:LogFlushQueue(a:state, a:dir)\n    let a:state.mode = 'commit'\n    let a:state.base = a:prefix . list[2]\n    if len(list[1])\n      let [a:state.base_module; a:state.parents] = split(list[1], ' ')\n    else\n      let a:state.base_module = list[2]\n      let a:state.parents = []\n    endif\n    let a:state.message = list[3]\n    let a:state.from = ''\n    let a:state.to = ''\n    let context = {}\n    let a:state.queue = [{\n          \\ 'valid': 1,\n          \\ 'context': context,\n          \\ 'filename': s:PathJoin(a:state.base, a:state.target),\n          \\ 'module': a:state.base_module . substitute(a:state.target, '^/', ':', ''),\n          \\ 'text': a:state.message}]\n    let a:state.child_found = 0\n    return queue\n  elseif type(a:line) == type(0)\n    return s:LogFlushQueue(a:state, a:dir)\n  elseif a:line =~# '^diff'\n    let a:state.mode = 'diffhead'\n    let a:state.from = ''\n    let a:state.to = ''\n  elseif a:state.mode ==# 'diffhead' && a:line =~# '^--- \\w/'\n    let a:state.from = a:line[6:-1]\n    let a:state.to = a:state.from\n  elseif a:state.mode ==# 'diffhead' && a:line =~# '^+++ \\w/'\n    let a:state.to = a:line[6:-1]\n    if empty(get(a:state, 'from', ''))\n      let a:state.from = a:state.to\n    endif\n  elseif a:line =~# '^@@[^@]*+\\d' && len(get(a:state, 'to', '')) && has_key(a:state, 'base')\n    let a:state.mode = 'hunk'\n    if empty(a:state.target) || a:state.target ==# '/' . a:state.to\n      if !a:state.child_found && len(a:state.queue) && a:state.queue[-1] ==# {'text': ''}\n        call remove(a:state.queue, -1)\n      endif\n      let a:state.child_found = 1\n      let offsets = map(split(matchstr(a:line, '^@\\+ \\zs[-+0-9, ]\\+\\ze @'), ' '), '+matchstr(v:val, \"\\\\d\\\\+\")')\n      let context = {}\n      if len(a:state.parents)\n        let from = \":\" . a:state.from\n        let context.diff = map(copy(a:state.parents), s:log_diff_context)\n      endif\n      call add(a:state.queue, {\n            \\ 'valid': 1,\n            \\ 'context': context,\n            \\ 'filename': s:VimSlash(a:state.base . '/' . a:state.to),\n            \\ 'module': a:state.base_module . ':' . a:state.to,\n            \\ 'lnum': offsets[-1],\n            \\ 'text': a:state.message . matchstr(a:line, ' @@\\+ .\\+')})\n    endif\n  elseif a:state.follow &&\n        \\ a:line =~# '^ \\%(mode change \\d\\|\\%(create\\|delete\\) mode \\d\\|\\%(rename\\|copy\\|rewrite\\) .* (\\d\\+%)$\\)'\n    let rename = matchstr(a:line, '^ \\%(copy\\|rename\\) \\zs.* => .*\\ze (\\d\\+%)$')\n    if len(rename)\n      let rename = rename =~# '{.* => .*}' ? rename : '{' . rename . '}'\n      if a:state.target ==# simplify('/' . substitute(rename, '{.* => \\(.*\\)}', '\\1', ''))\n        let a:state.target = simplify('/' . substitute(rename, '{\\(.*\\) => .*}', '\\1', ''))\n      endif\n    endif\n    if !get(a:state, 'ignore_summary')\n      call add(a:state.queue, {'text': a:line})\n    endif\n  elseif a:state.mode ==# 'commit' || a:state.mode ==# 'init'\n    call add(a:state.queue, {'text': a:line})\n  endif\n  return []\nendfunction\n\nfunction! fugitive#LogCommand(line1, count, range, bang, mods, args, type) abort\n  exe s:VersionCheck()\n  let dir = s:Dir()\n  exe s:DirCheck(dir)\n  let listnr = a:type =~# '^l' ? 0 : -1\n  let [args, after] = s:SplitExpandChain('log ' . a:args, s:Tree(dir))\n  call remove(args, 0)\n  let split = index(args, '--')\n  if split > 0\n    let paths = args[split : -1]\n    let args = args[0 : split - 1]\n  elseif split == 0\n    let paths = args\n    let args = []\n  else\n    let paths = []\n  endif\n  if a:line1 == 0 && a:count\n    let path = fugitive#Path(bufname(a:count), '/', dir)\n    let titlepre = ':0,' . a:count\n  elseif a:count >= 0\n    let path = fugitive#Path(@%, '/', dir)\n    let titlepre = a:count == 0 ? ':0,' . bufnr('') : ':'\n  else\n    let titlepre = ':'\n    let path = ''\n  endif\n  let range = ''\n  let extra_args = []\n  let extra_paths = []\n  let state = {'mode': 'init', 'child_found': 0, 'queue': [], 'follow': 0}\n  if path =~# '^/\\.git\\%(/\\|$\\)\\|^$'\n    let path = ''\n  elseif a:line1 == 0\n    let range = \"0,\" . (a:count ? a:count : bufnr(''))\n    let extra_paths = ['.' . path]\n    if (empty(paths) || paths ==# ['--']) && !s:HasOpt(args, '--no-follow')\n      let state.follow = 1\n      if !s:HasOpt(args, '--follow')\n        call insert(extra_args, '--follow')\n      endif\n      if !s:HasOpt(args, '--summary')\n        call insert(extra_args, '--summary')\n        let state.ignore_summary = 1\n      endif\n    endif\n    let state.ignore_commit = 1\n  elseif a:count > 0\n    if !s:HasOpt(args, '--merges', '--no-merges')\n      call insert(extra_args, '--no-merges')\n    endif\n    call add(args, '-L' . a:line1 . ',' . a:count . ':' . path[1:-1])\n    let state.ignore_commit = 1\n  endif\n  if len(path) && empty(filter(copy(args), 'v:val =~# \"^[^-]\"'))\n    let owner = s:Owner(@%, dir)\n    if len(owner)\n      call add(args, owner . (owner =~# '^\\x\\{40,}' ? '' : '^{}'))\n    endif\n  endif\n  if empty(extra_paths)\n    let path = ''\n  endif\n  if s:HasOpt(args, '-g', '--walk-reflogs')\n    let format = \"%gd %P\\t%H %gs\"\n  else\n    let format = \"%h %P\\t%H \" . g:fugitive_summary_format\n  endif\n  let cmd = ['--no-pager']\n  call extend(cmd, ['-c', 'diff.context=0', '-c', 'diff.noprefix=false', 'log'] +\n        \\ ['--no-color', '--no-ext-diff', '--pretty=format:fugitive ' . format] +\n        \\ args + extra_args + paths + extra_paths)\n  let state.target = path\n  let title = titlepre . (listnr < 0 ? 'Gclog ' : 'Gllog ') . s:fnameescape(args + paths)\n  return s:QuickfixStream(listnr, 'log', title, s:UserCommandList(dir) + cmd, !a:bang, a:mods, s:function('s:LogParse'), state, dir, s:DirUrlPrefix(dir)) . after\nendfunction\n\n\" Section: :Gedit, :Gpedit, :Gsplit, :Gvsplit, :Gtabedit, :Gread\n\nfunction! s:UsableWin(nr) abort\n  return a:nr && !getwinvar(a:nr, '&previewwindow') && !getwinvar(a:nr, '&winfixwidth') &&\n        \\ !getwinvar(a:nr, '&winfixbuf') &&\n        \\ (empty(getwinvar(a:nr, 'fugitive_status')) || getbufvar(winbufnr(a:nr), 'fugitive_type') !=# 'index') &&\n        \\ index(['gitrebase', 'gitcommit'], getbufvar(winbufnr(a:nr), '&filetype')) < 0 &&\n        \\ index(['nofile','help','quickfix', 'terminal'], getbufvar(winbufnr(a:nr), '&buftype')) < 0\nendfunction\n\nfunction! s:ArgSplit(string) abort\n  let string = a:string\n  let args = []\n  while string =~# '\\S'\n    let arg = matchstr(string, '^\\s*\\%(\\\\.\\|\\S\\)\\+')\n    let string = strpart(string, len(arg))\n    let arg = substitute(arg, '^\\s\\+', '', '')\n    call add(args, substitute(arg, '\\\\\\+[|\" ]', '\\=submatch(0)[len(submatch(0))/2 : -1]', 'g'))\n  endwhile\n  return args\nendfunction\n\nfunction! s:PlusEscape(string) abort\n  return substitute(a:string, '\\\\*[|\" ]', '\\=repeat(\"\\\\\", len(submatch(0))).submatch(0)', 'g')\nendfunction\n\nfunction! s:OpenParse(string, wants_cmd, wants_multiple) abort\n  let opts = []\n  let cmds = []\n  let args = s:ArgSplit(a:string)\n  while !empty(args)\n    if args[0] =~# '^++'\n      call add(opts, ' ' . s:PlusEscape(remove(args, 0)))\n    elseif a:wants_cmd && args[0] ==# '+'\n      call remove(args, 0)\n      call add(cmds, '$')\n    elseif a:wants_cmd && args[0] =~# '^+'\n      call add(cmds, remove(args, 0)[1:-1])\n    else\n      break\n    endif\n  endwhile\n  if !a:wants_multiple && empty(args)\n    let args = ['>:']\n  endif\n  let dir = s:Dir()\n  let wants_cmd = a:wants_cmd\n  let urls = []\n  for arg in args\n    let [url, lnum] = s:OpenExpand(dir, arg, wants_cmd)\n    if lnum\n      call insert(cmds, lnum)\n    endif\n    call add(urls, url)\n    let wants_cmd = 0\n  endfor\n\n  let pre = join(opts, '')\n  if len(cmds) > 1\n    let pre .= ' +' . s:PlusEscape(join(map(cmds, '\"exe \".string(v:val)'), '|'))\n  elseif len(cmds)\n    let pre .= ' +' . s:PlusEscape(cmds[0])\n  endif\n  return [a:wants_multiple ? urls : urls[0], pre]\nendfunction\n\nfunction! s:OpenExpand(dir, file, wants_cmd) abort\n  if a:file ==# '-'\n    let result = fugitive#Result()\n    if has_key(result, 'file')\n      let efile = result.file\n    else\n      throw 'fugitive: no previous command output'\n    endif\n  else\n    let efile = s:Expand(a:file)\n  endif\n  if efile =~# '^https\\=://'\n    let [url, lnum] = s:ResolveUrl(efile, a:dir)\n    return [url, a:wants_cmd ? lnum : 0]\n  endif\n  let url = s:Generate(efile, a:dir)\n  if a:wants_cmd && a:file[0] ==# '>' && efile[0] !=# '>' && get(b:, 'fugitive_type', '') isnot# 'tree' && &filetype !=# 'netrw'\n    let line = line('.')\n    if s:Slash(expand('%:p')) !=# s:Slash(url)\n      let diffcmd = 'diff'\n      let from = s:DirRev(@%)[1]\n      let to = s:DirRev(url)[1]\n      if empty(from) && empty(to)\n        let diffcmd = 'diff-files'\n        let args = ['--', expand('%:p'), url]\n      elseif empty(to)\n        let args = [from, '--', url]\n      elseif empty(from)\n        let args = [to, '--', expand('%:p')]\n        let reverse = 1\n      else\n        let args = [from, to]\n      endif\n      let [res, exec_error] = s:LinesError([a:dir, diffcmd, '-U0'] + args)\n      if !exec_error\n        call filter(res, 'v:val =~# \"^@@ \"')\n        call map(res, 'substitute(v:val, ''[-+]\\d\\+\\zs '', \",1 \", \"g\")')\n        call map(res, 'matchlist(v:val, ''^@@ -\\(\\d\\+\\),\\(\\d\\+\\) +\\(\\d\\+\\),\\(\\d\\+\\) @@'')[1:4]')\n        if exists('reverse')\n          call map(res, 'v:val[2:3] + v:val[0:1]')\n        endif\n        call filter(res, 'v:val[0] < '.line('.'))\n        let hunk = get(res, -1, [0,0,0,0])\n        if hunk[0] + hunk[1] > line('.')\n          let line = hunk[2] + max([1 - hunk[3], 0])\n        else\n          let line = hunk[2] + max([hunk[3], 1]) + line('.') - hunk[0] - max([hunk[1], 1])\n        endif\n      endif\n    endif\n    return [url, line]\n  endif\n  return [url, 0]\nendfunction\n\nfunction! fugitive#DiffClose() abort\n  let mywinnr = winnr()\n  for winnr in [winnr('#')] + range(winnr('$'),1,-1)\n    if winnr != mywinnr && getwinvar(winnr,'&diff')\n      execute winnr.'wincmd w'\n      close\n      if winnr('$') > 1\n        wincmd p\n      endif\n    endif\n  endfor\n  diffoff!\nendfunction\n\nfunction! s:BlurStatus() abort\n  if (&previewwindow || getwinvar(winnr(), '&winfixbuf') is# 1 || exists('w:fugitive_status')) && get(b:, 'fugitive_type', '') ==# 'index'\n    let winnrs = filter([winnr('#')] + range(1, winnr('$')), 's:UsableWin(v:val)')\n    if len(winnrs)\n      exe winnrs[0].'wincmd w'\n    else\n      belowright new +setl\\ bufhidden=delete\n    endif\n    if &diff\n      call fugitive#DiffClose()\n    endif\n  endif\nendfunction\n\nlet s:bang_edits = {'split': 'Git', 'vsplit': 'vertical Git', 'tabedit': 'tab Git', 'pedit': 'Git!'}\nfunction! fugitive#Open(cmd, bang, mods, arg, ...) abort\n  exe s:VersionCheck()\n  if a:bang\n    return 'echoerr ' . string(':G' . a:cmd . '! for temp buffer output has been replaced by :' . get(s:bang_edits, a:cmd, 'Git') . ' --paginate')\n  endif\n\n  try\n    let [file, pre] = s:OpenParse(a:arg, 1, 0)\n  catch /^fugitive:/\n    return 'echoerr ' . string(v:exception)\n  endtry\n  let mods = s:Mods(a:mods)\n  if a:cmd ==# 'edit'\n    call s:BlurStatus()\n  endif\n  return mods . a:cmd . pre . ' ' . s:fnameescape(file)\nendfunction\n\nfunction! fugitive#DropCommand(line1, count, range, bang, mods, arg, ...) abort\n  exe s:VersionCheck()\n\n  let mods = s:Mods(a:mods)\n  try\n    let [files, pre] = s:OpenParse(a:arg, 1, 1)\n  catch /^fugitive:/\n    return 'echoerr ' . string(v:exception)\n  endtry\n  if empty(files)\n    return 'drop'\n  endif\n  call s:BlurStatus()\n  return mods . 'drop' . ' ' . s:fnameescape(files) . substitute(pre, '^ *+', '|', '')\nendfunction\n\nfunction! s:ReadPrepare(line1, count, range, mods) abort\n  let mods = s:Mods(a:mods)\n  let after = a:count\n  if a:count < 0\n    let delete = 'silent 1,' . line('$') . 'delete_|'\n    let after = line('$')\n  elseif a:range == 2\n    let delete = 'silent ' . a:line1 . ',' . a:count . 'delete_|'\n  else\n    let delete = ''\n  endif\n  if foldlevel(after)\n    let pre = after . 'foldopen!|'\n  else\n    let pre = ''\n  endif\n  return [pre . 'keepalt ' . mods . after . 'read', '|' . delete . 'diffupdate' . (a:count < 0 ? '|' . line('.') : '')]\nendfunction\n\nfunction! fugitive#ReadCommand(line1, count, range, bang, mods, arg, ...) abort\n  exe s:VersionCheck()\n  let [read, post] = s:ReadPrepare(a:line1, a:count, a:range, a:mods)\n  try\n    let [file, pre] = s:OpenParse(a:arg, 0, 0)\n  catch /^fugitive:/\n    return 'echoerr ' . string(v:exception)\n  endtry\n  if file =~# '^fugitive:' && a:count is# 0\n    return 'exe ' .string('keepalt ' . s:Mods(a:mods) . fugitive#FileReadCmd(file, 0, pre)) . '|diffupdate'\n  endif\n  return read . ' ' . pre . ' ' . s:fnameescape(file) . post\nendfunction\n\nfunction! fugitive#EditComplete(A, L, P) abort\n  if a:A =~# '^>'\n    return map(s:FilterEscape(s:CompleteHeads(s:Dir()), a:A[1:-1]), \"'>' . v:val\")\n  else\n    return fugitive#CompleteObject(a:A, a:L, a:P)\n  endif\nendfunction\n\nfunction! fugitive#ReadComplete(A, L, P) abort\n  return fugitive#EditComplete(a:A, a:L, a:P)\nendfunction\n\n\" Section: :Gwrite, :Gwq\n\nfunction! fugitive#WriteCommand(line1, line2, range, bang, mods, arg, ...) abort\n  exe s:VersionCheck()\n  if s:cpath(expand('%:p'), fugitive#Find('.git/COMMIT_EDITMSG')) && empty(a:arg)\n    return (empty($GIT_INDEX_FILE) ? 'write|bdelete' : 'wq') . (a:bang ? '!' : '')\n  elseif get(b:, 'fugitive_type', '') ==# 'index' && empty(a:arg)\n    return 'Git commit'\n  elseif &buftype ==# 'nowrite' && getline(4) =~# '^[+-]\\{3\\} '\n    return 'echoerr ' . string('fugitive: :Gwrite from :Git diff has been removed in favor of :Git add --edit')\n  endif\n  let mytab = tabpagenr()\n  let mybufnr = bufnr('')\n  let args = s:ArgSplit(a:arg)\n  let after = ''\n  if get(args, 0) =~# '^+'\n    let after = '|' . remove(args, 0)[1:-1]\n  endif\n  try\n    let file = len(args) ? s:Generate(s:Expand(join(args, ' '))) : fugitive#Real(@%)\n  catch /^fugitive:/\n    return 'echoerr ' . string(v:exception)\n  endtry\n  if empty(file)\n    return 'echoerr '.string('fugitive: cannot determine file path')\n  endif\n  if file =~# '^fugitive:'\n    return 'write' . (a:bang ? '! ' : ' ') . s:fnameescape(file)\n  endif\n  exe s:DirCheck()\n  let always_permitted = s:cpath(fugitive#Real(@%), file) && empty(s:DirCommitFile(@%)[1])\n  if !always_permitted && !a:bang && (len(s:TreeChomp('diff', '--name-status', 'HEAD', '--', file)) || len(s:TreeChomp('ls-files', '--others', '--', file)))\n    let v:errmsg = 'fugitive: file has uncommitted changes (use ! to override)'\n    return 'echoerr v:errmsg'\n  endif\n  let treebufnr = 0\n  for nr in range(1,bufnr('$'))\n    if fnamemodify(bufname(nr),':p') ==# file\n      let treebufnr = nr\n    endif\n  endfor\n\n  if treebufnr > 0 && treebufnr != bufnr('')\n    let temp = tempname()\n    silent execute 'keepalt %write '.temp\n    for tab in [mytab] + range(1,tabpagenr('$'))\n      for winnr in range(1,tabpagewinnr(tab,'$'))\n        if tabpagebuflist(tab)[winnr-1] == treebufnr\n          execute 'tabnext '.tab\n          if winnr != winnr()\n            execute winnr.'wincmd w'\n            let restorewinnr = 1\n          endif\n          try\n            let lnum = line('.')\n            let last = line('$')\n            silent execute '$read '.temp\n            silent execute '1,'.last.'delete_'\n            silent write!\n            silent execute lnum\n            diffupdate\n            let did = 1\n          finally\n            if exists('restorewinnr')\n              wincmd p\n            endif\n            execute 'tabnext '.mytab\n          endtry\n          break\n        endif\n      endfor\n    endfor\n    if !exists('did')\n      call writefile(readfile(temp,'b'),file,'b')\n    endif\n  else\n    execute 'write! '.s:fnameescape(file)\n  endif\n\n  let message = s:ChompStderr(['add'] + (a:bang ? ['--force'] : []) + ['--', file])\n  if len(message)\n    let v:errmsg = 'fugitive: '.message\n    return 'echoerr v:errmsg'\n  endif\n  if s:cpath(fugitive#Real(@%), file) && s:DirCommitFile(@%)[1] =~# '^\\d$'\n    setlocal nomodified\n  endif\n\n  let one = fugitive#Find(':1:'.file)\n  let two = fugitive#Find(':2:'.file)\n  let three = fugitive#Find(':3:'.file)\n  for nr in range(1,bufnr('$'))\n    let name = fnamemodify(bufname(nr), ':p')\n    if bufloaded(nr) && !getbufvar(nr,'&modified') && (name ==# one || name ==# two || name ==# three)\n      execute nr.'bdelete'\n    endif\n  endfor\n\n  unlet! restorewinnr\n  let zero = fugitive#Find(':0:'.file)\n  exe s:DoAutocmd('BufWritePost ' . s:fnameescape(zero))\n  for tab in range(1,tabpagenr('$'))\n    for winnr in range(1,tabpagewinnr(tab,'$'))\n      let bufnr = tabpagebuflist(tab)[winnr-1]\n      let bufname = fnamemodify(bufname(bufnr), ':p')\n      if bufname ==# zero && bufnr != mybufnr\n        execute 'tabnext '.tab\n        if winnr != winnr()\n          execute winnr.'wincmd w'\n          let restorewinnr = 1\n        endif\n        try\n          let lnum = line('.')\n          let last = line('$')\n          silent execute '$read '.s:fnameescape(file)\n          silent execute '1,'.last.'delete_'\n          silent execute lnum\n          setlocal nomodified\n          diffupdate\n        finally\n          if exists('restorewinnr')\n            wincmd p\n          endif\n          execute 'tabnext '.mytab\n        endtry\n        break\n      endif\n    endfor\n  endfor\n  call fugitive#DidChange()\n  return 'checktime' . after\nendfunction\n\nfunction! fugitive#WqCommand(...) abort\n  let bang = a:4 ? '!' : ''\n  if s:cpath(expand('%:p'), fugitive#Find('.git/COMMIT_EDITMSG'))\n    return 'wq'.bang\n  endif\n  let result = call('fugitive#WriteCommand', a:000)\n  if result =~# '^\\%(write\\|wq\\|echoerr\\)'\n    return s:sub(result,'^write','wq')\n  else\n    return result.'|quit'.bang\n  endif\nendfunction\n\n\" Section: :Git push, :Git fetch\n\nfunction! s:CompletePush(A, L, P, ...) abort\n  let dir = a:0 ? a:1 : s:Dir()\n  let remote = matchstr(a:L, '\\u\\w*[! ] *.\\{-\\}\\s\\@<=\\zs[^-[:space:]]\\S*\\ze ')\n  if empty(remote)\n    let matches = s:LinesError([dir, 'remote'])[0]\n  elseif a:A =~# ':'\n    let lead = matchstr(a:A, '^[^:]*:')\n    let matches = s:LinesError([dir, 'ls-remote', remote])[0]\n    call filter(matches, 'v:val =~# \"\\t\" && v:val !~# \"{\"')\n    call map(matches, 'lead . s:sub(v:val, \"^.*\\t\", \"\")')\n  else\n    let matches = s:CompleteHeads(dir)\n    if a:A =~# '^[\\''\"]\\=+'\n      call map(matches, '\"+\" . v:val')\n    endif\n  endif\n  return s:FilterEscape(matches, a:A)\nendfunction\n\nfunction! fugitive#PushComplete(A, L, P, ...) abort\n  return s:CompleteSub('push', a:A, a:L, a:P, function('s:CompletePush'), a:000)\nendfunction\n\nfunction! fugitive#FetchComplete(A, L, P, ...) abort\n  return s:CompleteSub('fetch', a:A, a:L, a:P, function('s:CompleteRemote'), a:000)\nendfunction\n\nfunction! s:PushSubcommand(...) abort\n  return {'no_more': 1}\nendfunction\n\nfunction! s:FetchSubcommand(...) abort\n  return {'no_more': 1}\nendfunction\n\n\" Section: :Gdiff\n\naugroup fugitive_diff\n  autocmd!\n  autocmd BufWinLeave * nested\n        \\ if s:can_diffoff(+expand('<abuf>')) && s:diff_window_count() == 2 |\n        \\   call s:diffoff_all(s:Dir(+expand('<abuf>'))) |\n        \\ endif\n  autocmd BufWinEnter * nested\n        \\ if s:can_diffoff(+expand('<abuf>')) && s:diff_window_count() == 1 |\n        \\   call s:diffoff() |\n        \\ endif\naugroup END\n\nfunction! s:can_diffoff(buf) abort\n  return getwinvar(bufwinnr(a:buf), '&diff') &&\n        \\ !empty(getwinvar(bufwinnr(a:buf), 'fugitive_diff_restore'))\nendfunction\n\nfunction! fugitive#CanDiffoff(buf) abort\n  return s:can_diffoff(bufnr(a:buf))\nendfunction\n\nfunction! s:DiffModifier(count, default) abort\n  let fdc = matchstr(&diffopt, 'foldcolumn:\\zs\\d\\+')\n  if &diffopt =~# 'horizontal' && &diffopt !~# 'vertical'\n    return ''\n  elseif &diffopt =~# 'vertical'\n    return 'vertical '\n  elseif !get(g:, 'fugitive_diffsplit_directional_fit', a:default)\n    return ''\n  elseif winwidth(0) <= a:count * ((&tw ? &tw : 80) + (empty(fdc) ? 2 : fdc))\n    return ''\n  else\n    return 'vertical '\n  endif\nendfunction\n\nfunction! s:diff_window_count() abort\n  let c = 0\n  for nr in range(1,winnr('$'))\n    let c += getwinvar(nr,'&diff')\n  endfor\n  return c\nendfunction\n\nfunction! s:diffthis() abort\n  if !&diff\n    let w:fugitive_diff_restore = 1\n    diffthis\n  endif\nendfunction\n\nfunction! s:diffoff() abort\n  unlet! w:fugitive_diff_restore\n  diffoff\nendfunction\n\nfunction! s:diffoff_all(dir) abort\n  let curwin = winnr()\n  for nr in range(1,winnr('$'))\n    if getwinvar(nr, '&diff') && !empty(getwinvar(nr, 'fugitive_diff_restore'))\n      call setwinvar(nr, 'fugitive_diff_restore', '')\n    endif\n  endfor\n  if curwin != winnr()\n    execute curwin.'wincmd w'\n  endif\n  diffoff!\nendfunction\n\nfunction! s:IsConflicted() abort\n  return len(@%) && !empty(s:ChompDefault('', ['ls-files', '--unmerged', '--', expand('%:p')]))\nendfunction\n\nfunction! fugitive#Diffsplit(autodir, keepfocus, mods, arg, ...) abort\n  exe s:VersionCheck()\n  let args = s:ArgSplit(a:arg)\n  let post = ''\n  let autodir = a:autodir\n  while get(args, 0, '') =~# '^++'\n    if args[0] =~? '^++novertical$'\n      let autodir = 0\n    else\n      return 'echoerr ' . string('fugitive: unknown option ' . args[0])\n    endif\n    call remove(args, 0)\n  endwhile\n  if get(args, 0) =~# '^+'\n    let post = remove(args, 0)[1:-1]\n  endif\n  if exists(':DiffGitCached') && empty(args)\n    return s:Mods(a:mods) . 'DiffGitCached' . (len(post) ? '|' . post : '')\n  endif\n  let commit = s:DirCommitFile(@%)[1]\n  if a:mods =~# '\\<\\d*tab\\>'\n    let mods = substitute(a:mods, '\\<\\d*tab\\>', '', 'g')\n    let pre = matchstr(a:mods, '\\<\\d*tab\\>') . ' split'\n  else\n    let mods = 'keepalt ' . a:mods\n    let pre = ''\n  endif\n  let back = exists('*win_getid') ? 'call win_gotoid(' . win_getid() . ')' : 'wincmd p'\n  if (empty(args) || args[0] =~# '^>\\=:$') && a:keepfocus\n    exe s:DirCheck()\n    if commit =~# '^1\\=$' && s:IsConflicted()\n      let parents = [s:Relative(':2:'), s:Relative(':3:')]\n    elseif empty(commit)\n      let parents = [s:Relative(':0:')]\n    elseif commit =~# '^\\d\\=$'\n      let parents = [s:Relative('@:')]\n    elseif commit =~# '^\\x\\x\\+$'\n      let parents = s:LinesError(['rev-parse', commit . '^@'])[0]\n      call map(parents, 's:Relative(v:val . \":\")')\n    endif\n  endif\n  try\n    if exists('parents') && len(parents) > 1\n      exe pre\n      let mods = (autodir ? s:DiffModifier(len(parents) + 1, empty(args) || args[0] =~# '^>') : '') . s:Mods(mods, 'leftabove')\n      let nr = bufnr('')\n      if len(parents) > 1 && !&equalalways\n        let equalalways = 0\n        set equalalways\n      endif\n      execute mods 'split' s:fnameescape(fugitive#Find(parents[0]))\n      call s:Map('n', 'dp', ':diffput '.nr.'<Bar>diffupdate<CR>', '<silent>')\n      let nr2 = bufnr('')\n      call s:diffthis()\n      exe back\n      call s:Map('n', 'd2o', ':diffget '.nr2.'<Bar>diffupdate<CR>', '<silent>')\n      let mods = substitute(mods, '\\Cleftabove\\|rightbelow\\|aboveleft\\|belowright', '\\=submatch(0) =~# \"f\" ? \"rightbelow\" : \"leftabove\"', '')\n      for i in range(len(parents)-1, 1, -1)\n        execute mods 'split' s:fnameescape(fugitive#Find(parents[i]))\n        call s:Map('n', 'dp', ':diffput '.nr.'<Bar>diffupdate<CR>', '<silent>')\n        let nrx = bufnr('')\n        call s:diffthis()\n        exe back\n        call s:Map('n', 'd' . (i + 2) . 'o', ':diffget '.nrx.'<Bar>diffupdate<CR>', '<silent>')\n      endfor\n      call s:diffthis()\n      return post\n    elseif len(args)\n      let arg = join(args, ' ')\n      if arg ==# ''\n        return post\n      elseif arg ==# ':/'\n        exe s:DirCheck()\n        let file = s:Relative()\n      elseif arg ==# ':'\n        exe s:DirCheck()\n        let file = len(commit) ? s:Relative() : s:Relative(s:IsConflicted() ? ':1:' : ':0:')\n      elseif arg =~# '^:\\d$'\n        exe s:DirCheck()\n        let file = s:Relative(arg . ':')\n      elseif arg =~# '^[~^]\\d*$'\n        return 'echoerr ' . string('fugitive: change ' . arg . ' to !' . arg . ' to diff against ancestor')\n      else\n        try\n          let file = arg =~# '^:/.' ? fugitive#RevParse(arg) . s:Relative(':') : s:Expand(arg)\n        catch /^fugitive:/\n          return 'echoerr ' . string(v:exception)\n        endtry\n      endif\n      if a:keepfocus || arg =~# '^>'\n        let mods = s:Mods(a:mods, 'leftabove')\n      else\n        let mods = s:Mods(a:mods)\n      endif\n    elseif exists('parents')\n      let file = get(parents, -1, s:Relative(repeat('0', 40). ':'))\n      let mods = s:Mods(a:mods, 'leftabove')\n    elseif len(commit)\n      let file = s:Relative()\n      let mods = s:Mods(a:mods, 'rightbelow')\n    elseif s:IsConflicted()\n      let file = s:Relative(':1:')\n      let mods = s:Mods(a:mods, 'leftabove')\n      if get(g:, 'fugitive_legacy_commands', 1)\n        let post = 'echohl WarningMsg|echo \"Use :Gdiffsplit! for 3 way diff\"|echohl NONE|' . post\n      endif\n    else\n      exe s:DirCheck()\n      let file = s:Relative(':0:')\n      let mods = s:Mods(a:mods, 'leftabove')\n    endif\n    let spec = s:Generate(file)\n    if spec =~# '^fugitive:' && empty(s:DirCommitFile(spec)[2])\n      let spec = s:VimSlash(spec . s:Relative('/'))\n    endif\n    exe pre\n    let w:fugitive_diff_restore = 1\n    let mods = (autodir ? s:DiffModifier(2, empty(args) || args[0] =~# '^>') : '') . mods\n    if &diffopt =~# 'vertical'\n      let diffopt = &diffopt\n      set diffopt-=vertical\n    endif\n    execute mods 'diffsplit' s:fnameescape(spec)\n    let w:fugitive_diff_restore = 1\n    let winnr = winnr()\n    if getwinvar('#', '&diff')\n      if a:keepfocus\n        exe back\n      endif\n    endif\n    return post\n  catch /^fugitive:/\n    return 'echoerr ' . string(v:exception)\n  finally\n    if exists('l:equalalways')\n      let &g:equalalways = equalalways\n    endif\n    if exists('diffopt')\n      let &diffopt = diffopt\n    endif\n  endtry\nendfunction\n\n\" Section: :GMove, :GRemove\n\nfunction! s:Move(force, rename, destination) abort\n  exe s:VersionCheck()\n  let dir = s:Dir()\n  exe s:DirCheck(dir)\n  if s:DirCommitFile(@%)[1] !~# '^0\\=$' || empty(@%)\n    return 'echoerr ' . string('fugitive: mv not supported for this buffer')\n  endif\n  if a:rename\n    let default_root = expand('%:p:s?[\\/]$??:h') . '/'\n  else\n    let default_root = s:Tree(dir) . '/'\n  endif\n  if a:destination =~# '^:/:\\='\n    let destination = s:Tree(dir) . s:Expand(substitute(a:destination, '^:/:\\=', '', ''))\n  elseif a:destination =~# '^:(top)'\n    let destination = s:Expand(matchstr(a:destination, ')\\zs.*'))\n    if destination !~# '^/\\|^\\a\\+:'\n      let destination = s:Tree(dir) . '/' . destination\n    endif\n  elseif a:destination =~# '^:(\\%(top,literal\\|literal,top\\))'\n    let destination = s:Tree(dir) . matchstr(a:destination, ')\\zs.*')\n  elseif a:destination =~# '^:(literal)\\.\\.\\=\\%(/\\|$\\)'\n    let destination = simplify(getcwd() . '/' . matchstr(a:destination, ')\\zs.*'))\n  elseif a:destination =~# '^:(literal)'\n    let destination = simplify(default_root . matchstr(a:destination, ')\\zs.*'))\n  else\n    let destination = s:Expand(a:destination)\n    if destination =~# '^\\.\\.\\=\\%(/\\|$\\)' && !a:rename\n      let destination = simplify((a:rename ? default_root : getcwd() . '/') . destination)\n    elseif destination !~# '^\\a\\+:\\|^/'\n      let destination = default_root . destination\n    endif\n  endif\n  let destination = s:Slash(destination)\n  if isdirectory(@%)\n    setlocal noswapfile\n  endif\n  let exec = fugitive#Execute(['mv'] + (a:force ? ['-f'] : []) + ['--', expand('%:p'), destination], dir)\n  if exec.exit_status && exec.stderr !=# ['']\n    return 'echoerr ' .string('fugitive: '.s:JoinChomp(exec.stderr))\n  endif\n  if isdirectory(destination)\n    let destination = fnamemodify(s:sub(destination,'/$','').'/'.expand('%:t'),':.')\n  endif\n  let reload = '|call fugitive#DidChange(' . string(exec) . ')'\n  if empty(s:DirCommitFile(@%)[1])\n    if isdirectory(destination)\n      return 'keepalt edit '.s:fnameescape(destination) . reload\n    else\n      return 'keepalt saveas! '.s:fnameescape(destination) . reload\n    endif\n  else\n    return 'file '.s:fnameescape(fugitive#Find(':0:'.destination, dir)) . reload\n  endif\nendfunction\n\nfunction! fugitive#RenameComplete(A,L,P) abort\n  if a:A =~# '^[.:]\\=/'\n    return fugitive#CompletePath(a:A)\n  else\n    let pre = s:Slash(fnamemodify(expand('%:p:s?[\\/]$??'), ':h')) . '/'\n    return map(fugitive#CompletePath(pre.a:A), 'strpart(v:val, len(pre))')\n  endif\nendfunction\n\nfunction! fugitive#MoveCommand(line1, line2, range, bang, mods, arg, ...) abort\n  return s:Move(a:bang, 0, a:arg)\nendfunction\n\nfunction! fugitive#RenameCommand(line1, line2, range, bang, mods, arg, ...) abort\n  return s:Move(a:bang, 1, a:arg)\nendfunction\n\nfunction! s:Remove(after, force) abort\n  exe s:VersionCheck()\n  let dir = s:Dir()\n  exe s:DirCheck(dir)\n  if len(@%) && s:DirCommitFile(@%)[1] ==# ''\n    let cmd = ['rm']\n  elseif s:DirCommitFile(@%)[1] ==# '0'\n    let cmd = ['rm','--cached']\n  else\n    return 'echoerr ' . string('fugitive: rm not supported for this buffer')\n  endif\n  if a:force\n    let cmd += ['--force']\n  endif\n  let message = s:ChompStderr(cmd + ['--', expand('%:p')], dir)\n  if len(message)\n    let v:errmsg = 'fugitive: '.s:sub(message,'error:.*\\zs\\n\\(.*-f.*',' (add ! to force)')\n    return 'echoerr '.string(v:errmsg)\n  else\n    return a:after . (a:force ? '!' : ''). '|call fugitive#DidChange(' . string(dir) . ')'\n  endif\nendfunction\n\nfunction! fugitive#RemoveCommand(line1, line2, range, bang, mods, arg, ...) abort\n  return s:Remove('edit', a:bang)\nendfunction\n\nfunction! fugitive#UnlinkCommand(line1, line2, range, bang, mods, arg, ...) abort\n  return s:Remove('edit', a:bang)\nendfunction\n\nfunction! fugitive#DeleteCommand(line1, line2, range, bang, mods, arg, ...) abort\n  return s:Remove('bdelete', a:bang)\nendfunction\n\n\" Section: :Git blame\n\nfunction! s:Keywordprg() abort\n  let args = ' --git-dir=' . escape(FugitiveGitPath(s:GitDir()), \"\\\\\\\"' \")\n  if has('gui_running') && !has('win32')\n    return s:GitShellCmd() . ' --no-pager' . args . ' log -1'\n  else\n    return s:GitShellCmd() . args . ' show'\n  endif\nendfunction\n\nfunction! s:linechars(pattern) abort\n  let chars = strlen(s:gsub(matchstr(getline('.'), a:pattern), '.', '.'))\n  if &conceallevel > 1\n    for col in range(1, chars)\n      let chars -= synconcealed(line('.'), col)[0]\n    endfor\n  endif\n  return chars\nendfunction\n\nfunction! s:BlameBufnr(...) abort\n  let state = s:TempState(a:0 ? a:1 : bufnr(''))\n  if get(state, 'filetype', '') ==# 'fugitiveblame'\n    return get(state, 'origin_bufnr', -1)\n  else\n    return -1\n  endif\nendfunction\n\nfunction! s:BlameCommitFileLnum(...) abort\n  let line = a:0 ? a:1 : getline('.')\n  let state = a:0 > 1 ? a:2 : s:TempState()\n  if get(state, 'filetype', '') !=# 'fugitiveblame'\n    return ['', '', 0]\n  endif\n  let commit = matchstr(line, '^\\^\\=[?*]*\\zs\\x\\+')\n  if commit =~# '^0\\+$'\n    let commit = ''\n  elseif has_key(state, 'blame_reverse_end')\n    let commit = get(s:LinesError([state.git_dir, 'rev-list', '--ancestry-path', '--reverse', commit . '..' . state.blame_reverse_end])[0], 0, '')\n  endif\n  let lnum = +matchstr(line, ' \\zs\\d\\+\\ze \\%((\\| *\\d\\+)\\)')\n  let path = matchstr(line, '^\\^\\=[?*]*\\x* \\+\\%(\\d\\+ \\+\\d\\+ \\+\\)\\=\\zs.\\{-\\}\\ze\\s*\\d\\+ \\%((\\| *\\d\\+)\\)')\n  if empty(path) && lnum\n    let path = get(state, 'blame_file', '')\n  endif\n  return [commit, path, lnum]\nendfunction\n\nfunction! s:BlameLeave() abort\n  let state = s:TempState()\n  let bufwinnr = exists('*win_id2win') ? win_id2win(get(state, 'origin_winid')) : 0\n  if bufwinnr == 0\n    let bufwinnr = bufwinnr(get(state, 'origin_bufnr', -1))\n  endif\n  if get(state, 'filetype', '') ==# 'fugitiveblame' && bufwinnr > 0\n    let bufnr = bufnr('')\n    exe bufwinnr . 'wincmd w'\n    return bufnr . 'bdelete'\n  endif\n  return ''\nendfunction\n\nfunction! s:BlameQuit() abort\n  let cmd = s:BlameLeave()\n  if empty(cmd)\n    return 'bdelete'\n  elseif len(s:DirCommitFile(@%)[1])\n    return cmd . '|Gedit'\n  else\n    return cmd\n  endif\nendfunction\n\nfunction! fugitive#BlameComplete(A, L, P) abort\n  return s:CompleteSub('blame', a:A, a:L, a:P)\nendfunction\n\nfunction! s:BlameSubcommand(line1, count, range, bang, mods, options) abort\n  let dir = s:Dir(a:options)\n  exe s:DirCheck(dir)\n  let flags = copy(a:options.subcommand_args)\n  let i = 0\n  let raw = 0\n  let commits = []\n  let files = []\n  let ranges = []\n  if a:line1 > 0 && a:count > 0 && a:range != 1\n    call extend(ranges, ['-L', a:line1 . ',' . a:count])\n  endif\n  while i < len(flags)\n    let match = matchlist(flags[i], '^\\(-[a-zABDFH-KN-RT-Z]\\)\\ze\\(.*\\)')\n    if len(match) && len(match[2])\n      call insert(flags, match[1])\n      let flags[i+1] = '-' . match[2]\n      continue\n    endif\n    let arg = flags[i]\n    if arg =~# '^-p$\\|^--\\%(help\\|porcelain\\|line-porcelain\\|incremental\\)$'\n      let raw = 1\n    elseif arg ==# '--contents' && i + 1 < len(flags)\n      call extend(commits, remove(flags, i, i+1))\n      continue\n    elseif arg ==# '-L' && i + 1 < len(flags)\n      call extend(ranges, remove(flags, i, i+1))\n      continue\n    elseif arg =~# '^--contents='\n      call add(commits, remove(flags, i))\n      continue\n    elseif arg =~# '^-L.'\n      call add(ranges, remove(flags, i))\n      continue\n    elseif arg =~# '^-[GLS]$\\|^--\\%(date\\|encoding\\|contents\\|ignore-rev\\|ignore-revs-file\\)$'\n      let i += 1\n      if i == len(flags)\n        echohl ErrorMsg\n        echo s:ChompStderr([dir, 'blame', arg])\n        echohl NONE\n        return ''\n      endif\n    elseif arg ==# '--'\n      if i + 1 < len(flags)\n        call extend(files, remove(flags, i + 1, -1))\n      endif\n      call remove(flags, i)\n      break\n    elseif arg !~# '^-' && (s:HasOpt(flags, '--not') || arg !~# '^\\^')\n      if index(flags, '--') >= 0\n        call add(commits, remove(flags, i))\n        continue\n      endif\n      if arg =~# '\\.\\.' && arg !~# '^\\.\\.\\=\\%(/\\|$\\)' && empty(commits)\n        call add(commits, remove(flags, i))\n        continue\n      endif\n      try\n        let dcf = s:DirCommitFile(fugitive#Find(arg, dir))\n        if len(dcf[1]) && empty(dcf[2])\n          call add(commits, remove(flags, i))\n          continue\n        endif\n      catch /^fugitive:/\n      endtry\n      call add(files, remove(flags, i))\n      continue\n    endif\n    let i += 1\n  endwhile\n  let file = substitute(get(files, 0, get(s:TempState(), 'blame_file', s:Relative('./', dir))), '^\\.\\%(/\\|$\\)', '', '')\n  if empty(commits) && len(files) > 1\n    call add(commits, remove(files, 1))\n  endif\n  exe s:BlameLeave()\n  try\n    let cmd = a:options.flags + ['--no-pager', '-c', 'blame.coloring=none', '-c', 'blame.blankBoundary=false', a:options.subcommand, '--show-number']\n    call extend(cmd, filter(copy(flags), 'v:val !~# \"\\\\v^%(-b|--%(no-)=color-.*|--progress)$\"'))\n    if a:count > 0 && empty(ranges)\n      let cmd += ['-L', (a:line1 ? a:line1 : line('.')) . ',' . (a:line1 ? a:line1 : line('.'))]\n    endif\n    call extend(cmd, ranges)\n    let tempname = tempname()\n    let temp = tempname . (raw ? '' : '.fugitiveblame')\n    if len(commits)\n      let cmd += commits\n    elseif empty(files) && len(matchstr(s:DirCommitFile(@%)[1], '^\\x\\x\\+$'))\n      let cmd += [matchstr(s:DirCommitFile(@%)[1], '^\\x\\x\\+$')]\n    elseif empty(files) && !s:HasOpt(flags, '--reverse')\n      if &modified || !empty(s:DirCommitFile(@%)[1])\n        let cmd += ['--contents', tempname . '.in']\n        silent execute 'noautocmd keepalt %write ' . s:fnameescape(tempname . '.in')\n        let delete_in = 1\n      elseif &autoread\n        exe 'checktime ' . bufnr('')\n      endif\n    else\n      call fugitive#Autowrite()\n    endif\n    let basecmd = [{'git': a:options.git}, dir, '--literal-pathspecs'] + cmd + ['--'] + (len(files) ? files : [file])\n    let [err, exec_error] = s:StdoutToFile(temp, basecmd)\n    if exists('delete_in')\n      call delete(tempname . '.in')\n    endif\n    redraw\n    try\n      if exec_error\n        let lines = split(err, \"\\n\")\n        if empty(lines)\n          let lines = readfile(temp)\n        endif\n        for i in range(len(lines))\n          if lines[i] =~# '^error: \\|^fatal: '\n            echohl ErrorMsg\n            echon lines[i]\n            echohl NONE\n            break\n          else\n            echon lines[i]\n          endif\n          if i != len(lines) - 1\n            echon \"\\n\"\n          endif\n        endfor\n        return ''\n      endif\n      let temp_state = {\n            \\ 'git': a:options.git,\n            \\ 'flags': a:options.flags,\n            \\ 'args': [a:options.subcommand] + a:options.subcommand_args,\n            \\ 'git_dir': s:GitDir(a:options),\n            \\ 'cwd': s:UserCommandCwd(a:options),\n            \\ 'filetype': (raw ? 'git' : 'fugitiveblame'),\n            \\ 'blame_options': a:options,\n            \\ 'blame_flags': flags,\n            \\ 'blame_file': file}\n      if s:HasOpt(flags, '--reverse')\n        let temp_state.blame_reverse_end = matchstr(get(commits, 0, ''), '\\.\\.\\zs.*')\n      endif\n      if a:line1 == 0 && a:count == 1\n        if get(a:options, 'curwin')\n          let edit = 'edit'\n        elseif a:bang\n          let edit = 'pedit'\n        else\n          let edit = 'split'\n        endif\n        return s:BlameCommit(s:Mods(a:mods) . edit, get(readfile(temp), 0, ''), temp_state)\n      elseif (a:line1 == 0 || a:range == 1) && a:count > 0\n        let edit = s:Mods(a:mods) . get(['edit', 'split', 'pedit', 'vsplit', 'tabedit', 'edit'], a:count - (a:line1 ? a:line1 : 1), 'split')\n        return s:BlameCommit(edit, get(readfile(temp), 0, ''), temp_state)\n      else\n        let temp = s:Resolve(temp)\n        let temp_state.file = temp\n        call s:RunSave(temp_state)\n        if len(ranges + commits + files) || raw\n          let reload = '|call fugitive#DidChange(fugitive#Result(' . string(temp_state.file) . '))'\n          let mods = s:Mods(a:mods)\n          if a:count != 0\n            exe 'silent keepalt' mods get(a:options, 'curwin') ? 'edit' : 'split' s:fnameescape(temp)\n          elseif !&modified || a:bang || &bufhidden ==# 'hide' || (empty(&bufhidden) && &hidden)\n            exe 'silent' mods 'edit' . (a:bang ? '! ' : ' ') . s:fnameescape(temp)\n          else\n            return mods . 'edit ' . s:fnameescape(temp) . reload\n          endif\n          return reload[1 : -1]\n        endif\n        let tabmod = matchstr(a:mods, '\\<\\d*tab\\>')\n        let mods = substitute(a:mods, '\\<\\d*tab\\>', '', 'g')\n        if !empty(tabmod)\n          silent execute tabmod . 'edit %'\n        endif\n        let temp_state.origin_bufnr = bufnr('')\n        if exists('*win_getid')\n          let temp_state.origin_winid = win_getid()\n        endif\n        let restore = []\n        for winnr in range(winnr('$'),1,-1)\n          if getwinvar(winnr, '&scrollbind')\n            if !&l:scrollbind\n              call setwinvar(winnr, '&scrollbind', 0)\n            elseif winnr != winnr() && getwinvar(winnr, '&foldenable')\n              call setwinvar(winnr, '&foldenable', 0)\n              call add(restore, 'call setwinvar(bufwinnr('.winbufnr(winnr).'),\"&foldenable\",1)')\n            endif\n          endif\n          let win_blame_bufnr = s:BlameBufnr(winbufnr(winnr))\n          if getwinvar(winnr, '&scrollbind') ? win_blame_bufnr == temp_state.origin_bufnr : win_blame_bufnr > 0\n            execute winbufnr(winnr).'bdelete'\n          endif\n        endfor\n        let restore_winnr = get(temp_state, 'origin_winid', 'bufwinnr(' . temp_state.origin_bufnr . ')')\n        if !&l:scrollbind\n          call add(restore, 'call setwinvar(' . restore_winnr . ',\"&scrollbind\",0)')\n        endif\n        if &l:wrap\n          call add(restore, 'call setwinvar(' . restore_winnr . ',\"&wrap\",1)')\n        endif\n        if &l:foldenable\n          call add(restore, 'call setwinvar(' . restore_winnr . ',\"&foldenable\",1)')\n        endif\n        setlocal scrollbind nowrap nofoldenable\n        let top = line('w0') + &scrolloff\n        let current = line('.')\n        exe 'silent keepalt' (a:bang ? s:Mods(mods) . 'split' : s:Mods(mods, 'leftabove') . 'vsplit') s:fnameescape(temp)\n        let w:fugitive_leave = join(restore, '|')\n        execute top\n        normal! zt\n        execute current\n        setlocal nonumber scrollbind nowrap foldcolumn=0 nofoldenable winfixwidth\n        if exists('&winfixbuf')\n          setlocal winfixbuf\n        endif\n        if exists('+relativenumber')\n          setlocal norelativenumber\n        endif\n        if exists('+signcolumn')\n          setlocal signcolumn=no\n        endif\n        execute \"vertical resize \".(s:linechars('.\\{-\\}\\s\\+\\d\\+\\ze)')+1)\n        redraw\n        syncbind\n        exe s:DoAutocmdChanged(temp_state)\n      endif\n    endtry\n    return ''\n  catch /^fugitive:/\n    return 'echoerr ' . string(v:exception)\n  endtry\nendfunction\n\nfunction! s:BlameCommit(cmd, ...) abort\n  let line = a:0 ? a:1 : getline('.')\n  let state = a:0 ? a:2 : s:TempState()\n  let sigil = has_key(state, 'blame_reverse_end') ? '-' : '+'\n  let mods = (s:BlameBufnr() < 0 ? '' : &splitbelow ? \"botright \" : \"topleft \")\n  let [commit, path, lnum] = s:BlameCommitFileLnum(line, state)\n  if empty(commit) && len(path) && has_key(state, 'blame_reverse_end')\n    let path = (len(state.blame_reverse_end) ? state.blame_reverse_end . ':' : ':(top)') . path\n    return fugitive#Open(mods . a:cmd, 0, '', '+' . lnum . ' ' . s:fnameescape(path), ['+' . lnum, path])\n  endif\n  if commit =~# '^0*$'\n    return 'echoerr ' . string('fugitive: no commit')\n  endif\n  if line =~# '^\\^' && !has_key(state, 'blame_reverse_end')\n    let path = commit . ':' . path\n    return fugitive#Open(mods . a:cmd, 0, '', '+' . lnum . ' ' . s:fnameescape(path), ['+' . lnum, path])\n  endif\n  let cmd = fugitive#Open(mods . a:cmd, 0, '', commit, [commit])\n  if cmd =~# '^echoerr'\n    return cmd\n  endif\n  execute cmd\n  if a:cmd ==# 'pedit' || empty(path)\n    return ''\n  endif\n  if search('^diff .* b/\\M'.escape(path,'\\').'$','W')\n    call search('^+++')\n    let head = line('.')\n    while search('^@@ \\|^diff ') && getline('.') =~# '^@@ '\n      let top = +matchstr(getline('.'),' ' . sigil .'\\zs\\d\\+')\n      let len = +matchstr(getline('.'),' ' . sigil . '\\d\\+,\\zs\\d\\+')\n      if lnum >= top && lnum <= top + len\n        let offset = lnum - top\n        if &scrolloff\n          +\n          normal! zt\n        else\n          normal! zt\n          +\n        endif\n        while offset > 0 && line('.') < line('$')\n          +\n          if getline('.') =~# '^[ ' . sigil . ']'\n            let offset -= 1\n          endif\n        endwhile\n        return 'normal! zv'\n      endif\n    endwhile\n    execute head\n    normal! zt\n  endif\n  return ''\nendfunction\n\nfunction! s:BlameJump(suffix, ...) abort\n  let suffix = a:suffix\n  let [commit, path, lnum] = s:BlameCommitFileLnum()\n  if empty(path)\n    return 'echoerr ' . string('fugitive: could not determine filename for blame')\n  endif\n  if commit =~# '^0*$'\n    let commit = '@'\n    let suffix = ''\n  endif\n  let offset = line('.') - line('w0')\n  let state = s:TempState()\n  let flags = get(state, 'blame_flags', [])\n  let blame_bufnr = s:BlameBufnr()\n  if blame_bufnr > 0\n    let bufnr = bufnr('')\n    let winnr = bufwinnr(blame_bufnr)\n    if winnr > 0\n      exe winnr.'wincmd w'\n      exe bufnr.'bdelete'\n    endif\n    execute 'Gedit' s:fnameescape(commit . suffix . ':' . path)\n    execute lnum\n  endif\n  let my_bufnr = bufnr('')\n  if blame_bufnr < 0\n    let blame_args = flags + [commit . suffix, '--', path]\n    let result = s:BlameSubcommand(0, 0, 0, 0, '', extend({'subcommand_args': blame_args}, state.blame_options, 'keep'))\n  else\n    let blame_args = flags\n    let result = s:BlameSubcommand(-1, -1, 0, 0, '', extend({'subcommand_args': blame_args}, state.blame_options, 'keep'))\n  endif\n  if bufnr('') == my_bufnr\n    return result\n  endif\n  execute result\n  execute lnum\n  let delta = line('.') - line('w0') - offset\n  if delta > 0\n    execute 'normal! '.delta.\"\\<C-E>\"\n  elseif delta < 0\n    execute 'normal! '.(-delta).\"\\<C-Y>\"\n  endif\n  keepjumps syncbind\n  redraw\n  echo ':Git blame' s:fnameescape(blame_args)\n  return ''\nendfunction\n\nlet s:hash_colors = {}\n\nfunction! fugitive#BlameSyntax() abort\n  let conceal = has('conceal') ? ' conceal' : ''\n  let flags = get(s:TempState(), 'blame_flags', [])\n  syn spell notoplevel\n  syn match FugitiveblameBlank                      \"^\\s\\+\\s\\@=\" nextgroup=FugitiveblameAnnotation,FugitiveblameScoreDebug,FugitiveblameOriginalFile,FugitiveblameOriginalLineNumber skipwhite\n  syn match FugitiveblameHash       \"\\%(^\\^\\=[?*]*\\)\\@<=\\<\\x\\{7,\\}\\>\" nextgroup=FugitiveblameAnnotation,FugitiveblameScoreDebug,FugitiveblameOriginalLineNumber,FugitiveblameOriginalFile skipwhite\n  if s:HasOpt(flags, '-b') || FugitiveConfigGet('blame.blankBoundary') =~# '^1$\\|^true$'\n    syn match FugitiveblameBoundaryIgnore \"^\\^[*?]*\\x\\{7,\\}\\>\" nextgroup=FugitiveblameAnnotation,FugitiveblameScoreDebug,FugitiveblameOriginalLineNumber,FugitiveblameOriginalFile skipwhite\n  else\n    syn match FugitiveblameBoundary \"^\\^\"\n  endif\n  syn match FugitiveblameScoreDebug        \" *\\d\\+\\s\\+\\d\\+\\s\\@=\" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile contained skipwhite\n  syn region FugitiveblameAnnotation matchgroup=FugitiveblameDelimiter start=\"(\" end=\"\\%(\\s\\d\\+\\)\\@<=)\" contained keepend oneline\n  syn match FugitiveblameTime \"\\<[0-9:/+-][0-9:/+ -]*[0-9:/+-]\\%(\\s\\+\\d\\+)\\)\\@=\" contained containedin=FugitiveblameAnnotation\n  exec 'syn match FugitiveblameLineNumber         \"\\s[[:digit:][:space:]]\\{0,' . (len(line('$'))-1). '\\}\\d)\\@=\" contained containedin=FugitiveblameAnnotation' conceal\n  exec 'syn match FugitiveblameOriginalFile       \"\\s\\%(\\f\\+\\D\\@<=\\|\\D\\@=\\f\\+\\)\\%(\\%(\\s\\+\\d\\+\\)\\=\\s\\%((\\|\\s*\\d\\+)\\)\\)\\@=\" contained nextgroup=FugitiveblameOriginalLineNumber,FugitiveblameAnnotation skipwhite' (s:HasOpt(flags, '--show-name', '-f') ? '' : conceal)\n  exec 'syn match FugitiveblameOriginalLineNumber \"\\s*\\d\\+\\%(\\s(\\)\\@=\" contained nextgroup=FugitiveblameAnnotation skipwhite' (s:HasOpt(flags, '--show-number', '-n') ? '' : conceal)\n  exec 'syn match FugitiveblameOriginalLineNumber \"\\s*\\d\\+\\%(\\s\\+\\d\\+)\\)\\@=\" contained nextgroup=FugitiveblameShort skipwhite' (s:HasOpt(flags, '--show-number', '-n') ? '' : conceal)\n  syn match FugitiveblameShort              \" \\+\\d\\+)\" contained contains=FugitiveblameLineNumber\n  syn match FugitiveblameNotCommittedYet \"(\\@<=Not Committed Yet\\>\" contained containedin=FugitiveblameAnnotation\n  hi def link FugitiveblameBoundary           Keyword\n  hi def link FugitiveblameHash               Identifier\n  hi def link FugitiveblameBoundaryIgnore     Ignore\n  hi def link FugitiveblameUncommitted        Ignore\n  hi def link FugitiveblameScoreDebug         Debug\n  hi def link FugitiveblameTime               PreProc\n  hi def link FugitiveblameLineNumber         Number\n  hi def link FugitiveblameOriginalFile       String\n  hi def link FugitiveblameOriginalLineNumber Float\n  hi def link FugitiveblameShort              FugitiveblameDelimiter\n  hi def link FugitiveblameDelimiter          Delimiter\n  hi def link FugitiveblameNotCommittedYet    Comment\n  if !get(g:, 'fugitive_dynamic_colors', 1) && !s:HasOpt(flags, '--color-lines') || s:HasOpt(flags, '--no-color-lines')\n    return\n  endif\n  let seen = {}\n  for x in split('01234567890abcdef', '\\zs')\n    exe 'syn match FugitiveblameHashGroup'.x '\"\\%(^\\^\\=[*?]*\\)\\@<='.x.'\\x\\{5,\\}\\>\" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite'\n  endfor\n  for lnum in range(1, line('$'))\n    let orig_hash = matchstr(getline(lnum), '^\\^\\=[*?]*\\zs\\x\\{6\\}')\n    let hash = orig_hash\n    let hash = substitute(hash, '\\(\\x\\)\\x', '\\=submatch(1).printf(\"%x\", 15-str2nr(submatch(1),16))', 'g')\n    let hash = substitute(hash, '\\(\\x\\x\\)', '\\=printf(\"%02x\", str2nr(submatch(1),16)*3/4+32)', 'g')\n    if hash ==# '' || orig_hash ==# '000000' || has_key(seen, hash)\n      continue\n    endif\n    let seen[hash] = 1\n    if &t_Co == 256\n      let [s, r, g, b; __] = map(matchlist(orig_hash, '\\(\\x\\)\\x\\(\\x\\)\\x\\(\\x\\)\\x'), 'str2nr(v:val,16)')\n      let color = 16 + (r + 1) / 3 * 36 + (g + 1) / 3 * 6 + (b + 1) / 3\n      if color == 16\n        let color = 235\n      elseif color == 231\n        let color = 255\n      endif\n      let s:hash_colors[hash] = ' ctermfg='.color\n    else\n      let s:hash_colors[hash] = ''\n    endif\n    let pattern = substitute(orig_hash, '^\\(\\x\\)\\x\\(\\x\\)\\x\\(\\x\\)\\x$', '\\1\\\\x\\2\\\\x\\3\\\\x', '') . '*'\n    exe 'syn match FugitiveblameHash'.hash.'       \"\\%(^\\^\\=[*?]*\\)\\@<='.pattern.'\" contained containedin=FugitiveblameHashGroup' . orig_hash[0]\n  endfor\n  syn match FugitiveblameUncommitted \"\\%(^\\^\\=[?*]*\\)\\@<=\\<0\\{7,\\}\\>\" nextgroup=FugitiveblameAnnotation,FugitiveblameScoreDebug,FugitiveblameOriginalLineNumber,FugitiveblameOriginalFile skipwhite\n  call s:BlameRehighlight()\nendfunction\n\nfunction! s:BlameRehighlight() abort\n  for [hash, cterm] in items(s:hash_colors)\n    if !empty(cterm) || has('gui_running') || has('termguicolors') && &termguicolors\n      exe 'hi FugitiveblameHash'.hash.' guifg=#' . hash . cterm\n    else\n      exe 'hi link FugitiveblameHash'.hash.' Identifier'\n    endif\n  endfor\nendfunction\n\nfunction! s:BlameMaps(is_ftplugin) abort\n  let ft = a:is_ftplugin\n  call s:MapGitOps(ft)\n  call s:Map('n', '<F1>', ':help :Git_blame<CR>', '<silent>', ft)\n  call s:Map('n', 'g?',   ':help :Git_blame<CR>', '<silent>', ft)\n  call s:Map('n', 'gq',   ':exe <SID>BlameQuit()<CR>', '<silent>', ft)\n  call s:Map('n', '<2-LeftMouse>', ':<C-U>exe <SID>BlameCommit(\"exe <SID>BlameLeave()<Bar>edit\")<CR>', '<silent>', ft)\n  call s:Map('n', '<CR>', ':<C-U>exe <SID>BlameCommit(\"exe <SID>BlameLeave()<Bar>edit\")<CR>', '<silent>', ft)\n  call s:Map('n', '-',    ':<C-U>exe <SID>BlameJump(\"\")<CR>', '<silent>', ft)\n  call s:Map('n', 's',    ':<C-U>exe <SID>BlameJump(\"\")<CR>', '<silent>', ft)\n  call s:Map('n', 'u',    ':<C-U>exe <SID>BlameJump(\"\")<CR>', '<silent>', ft)\n  call s:Map('n', 'P',    ':<C-U>if !v:count<Bar>echoerr \"Use ~ (or provide a count)\"<Bar>else<Bar>exe <SID>BlameJump(\"^\".v:count1)<Bar>endif<CR>', '<silent>', ft)\n  call s:Map('n', '~',    ':<C-U>exe <SID>BlameJump(\"~\".v:count1)<CR>', '<silent>', ft)\n  call s:Map('n', 'i',    ':<C-U>exe <SID>BlameCommit(\"exe <SID>BlameLeave()<Bar>edit\")<CR>', '<silent>', ft)\n  call s:Map('n', 'o',    ':<C-U>exe <SID>BlameCommit(\"split\")<CR>', '<silent>', ft)\n  call s:Map('n', 'O',    ':<C-U>exe <SID>BlameCommit(\"tabedit\")<CR>', '<silent>', ft)\n  call s:Map('n', 'p',    ':<C-U>exe <SID>BlameCommit(\"pedit\")<CR>', '<silent>', ft)\n  exe s:Map('n', '.',    \":<C-U> <C-R>=substitute(<SID>BlameCommitFileLnum()[0],'^$','@','')<CR><Home>\", '', ft)\n  exe s:Map('n', '(',    \"-\", '', ft)\n  exe s:Map('n', ')',    \"+\", '', ft)\n  call s:Map('n', 'A',    \":<C-u>exe 'vertical resize '.(<SID>linechars('.\\\\{-\\\\}\\\\ze [0-9:/+-][0-9:/+ -]* \\\\d\\\\+)')+1+v:count)<CR>\", '<silent>', ft)\n  call s:Map('n', 'C',    \":<C-u>exe 'vertical resize '.(<SID>linechars('^\\\\S\\\\+')+1+v:count)<CR>\", '<silent>', ft)\n  call s:Map('n', 'D',    \":<C-u>exe 'vertical resize '.(<SID>linechars('.\\\\{-\\\\}\\\\ze\\\\d\\\\ze\\\\s\\\\+\\\\d\\\\+)')+1-v:count)<CR>\", '<silent>', ft)\nendfunction\n\nfunction! fugitive#BlameFileType() abort\n  setlocal nomodeline\n  setlocal foldmethod=manual\n  if len(s:GitDir())\n    let &l:keywordprg = s:Keywordprg()\n  endif\n  let b:undo_ftplugin = 'setl keywordprg= foldmethod<'\n  if exists('+concealcursor')\n    setlocal concealcursor=nc conceallevel=2\n    let b:undo_ftplugin .= ' concealcursor< conceallevel<'\n  endif\n  if &modifiable\n    return ''\n  endif\n  call s:BlameMaps(1)\nendfunction\n\nfunction! s:BlameCursorSync(bufnr, line) abort\n  if a:line == line('.')\n    return\n  endif\n  if get(s:TempState(), 'origin_bufnr') == a:bufnr || get(s:TempState(a:bufnr), 'origin_bufnr') == bufnr('')\n    if &startofline\n      execute a:line\n    else\n      let pos = getpos('.')\n      let pos[1] = a:line\n      call setpos('.', pos)\n    endif\n  endif\nendfunction\n\naugroup fugitive_blame\n  autocmd!\n  autocmd ColorScheme,GUIEnter * call s:BlameRehighlight()\n  autocmd BufWinLeave * execute getwinvar(+bufwinnr(+expand('<abuf>')), 'fugitive_leave')\n  autocmd WinLeave * let s:cursor_for_blame = [bufnr(''), line('.')]\n  autocmd WinEnter * if exists('s:cursor_for_blame') | call call('s:BlameCursorSync', s:cursor_for_blame) | endif\naugroup END\n\n\" Section: :GBrowse\n\nfunction! s:BrowserOpen(url, mods, echo_copy) abort\n  let [_, main, query, anchor; __] = matchlist(a:url, '^\\([^#?]*\\)\\(?[^#]*\\)\\=\\(#.*\\)\\=')\n  let url = main . tr(query, ' ', '+') . anchor\n  let url = substitute(url, '[ <>\\|\"]', '\\=\"%\".printf(\"%02X\",char2nr(submatch(0)))', 'g')\n  let mods = s:Mods(a:mods)\n  if a:echo_copy\n    if has('clipboard')\n      let @+ = url\n    endif\n    return 'echo '.string(url)\n  elseif exists(':Browse') == 2\n    return 'echo '.string(url).'|' . mods . 'Browse '.url\n  elseif exists(':OpenBrowser') == 2\n    return 'echo '.string(url).'|' . mods . 'OpenBrowser '.url\n  else\n    if !exists('g:loaded_netrw')\n      runtime! autoload/netrw.vim\n      runtime! autoload/netrw/os.vim\n    endif\n    if exists('*netrw#Open')\n      return 'echo '.string(url).'|' . mods . 'call netrw#Open('.string(url).')'\n    elseif exists('*netrw#os#Open')\n      return 'echo '.string(url).'|' . mods . 'call netrw#os#Open('.string(url).')'\n    elseif exists('*netrw#BrowseX')\n      return 'echo '.string(url).'|' . mods . 'call netrw#BrowseX('.string(url).', 0)'\n    elseif exists('*netrw#NetrwBrowseX')\n      return 'echo '.string(url).'|' . mods . 'call netrw#NetrwBrowseX('.string(url).', 0)'\n    elseif has('nvim-0.10')\n      return mods . 'echo luaeval(\"({vim.ui.open(_A)})[2] or _A\", ' . string(url) . ')'\n    else\n      return 'echoerr ' . string('Netrw not found. Define your own :Browse to use :GBrowse')\n    endif\n  endif\nendfunction\n\nfunction! fugitive#BrowseCommand(line1, count, range, bang, mods, arg, ...) abort\n  exe s:VersionCheck()\n  let dir = s:Dir()\n  try\n    let arg = a:arg\n    if arg =~# '^++\\%([Gg]it\\)\\=[Rr]emote='\n      let remote = matchstr(arg, '^++\\%([Gg]it\\)\\=[Rr]emote=\\zs\\S\\+')\n      let arg = matchstr(arg, '\\s\\zs\\S.*')\n    endif\n    let validremote = '\\.\\%(git\\)\\=\\|\\.\\=/.*\\|\\a[[:alnum:]_-]*\\%(://.\\{-\\}\\)\\='\n    if arg ==# '-'\n      let remote = ''\n      let rev = ''\n      let result = fugitive#Result()\n      if filereadable(get(result, 'file', ''))\n        let rev = s:fnameescape(result.file)\n      else\n        return 'echoerr ' . string('fugitive: could not find prior :Git invocation')\n      endif\n    elseif !exists('l:remote')\n      let remote = matchstr(arg, '\\\\\\@<!\\%(\\\\\\\\\\)*[!@]\\zs\\%('.validremote.'\\)$')\n      let rev = strpart(arg, 0, len(arg) - len(remote) - (empty(remote) ? 0 : 1))\n    else\n      let rev = arg\n    endif\n    let expanded = s:Expand(rev)\n    if expanded =~? '^\\a\\a\\+:[\\/][\\/]' && expanded !~? '^fugitive:'\n      return s:BrowserOpen(s:Slash(expanded), a:mods, a:bang)\n    endif\n    if !exists('l:result')\n      let result = s:TempState(empty(expanded) ? bufnr('') : expanded)\n    endif\n    if !get(result, 'origin_bufnr', 1) && filereadable(get(result, 'file', ''))\n      for line in readfile(result.file, '', 4096)\n        let rev = s:fnameescape(matchstr(line, '\\<https\\=://[^[:space:]<>]*[^[:space:]<>.,;:\"''!?]'))\n        if len(rev)\n          return s:BrowserOpen(rev, a:mods, a:bang)\n        endif\n      endfor\n      return 'echoerr ' . string('fugitive: no URL found in output of :Git')\n    endif\n    if empty(remote) && expanded =~# '^[^-./:^~][^:^~]*$' && !empty(dir)\n      let config = fugitive#Config(dir)\n      if !empty(FugitiveConfigGet('remote.' . expanded . '.url', config))\n        let remote = expanded\n        let expanded = ''\n      endif\n    endif\n    if empty(expanded)\n      let bufname = &buftype =~# '^\\%(nofile\\|terminal\\)$' ? '' : s:BufName('%')\n      let expanded = s:DirRev(bufname)[1]\n      if empty(expanded)\n        let expanded = fugitive#Path(bufname, ':(top)', dir)\n      endif\n      if a:count > 0 && has_key(result, 'origin_bufnr') && a:range != 2\n        let blame = s:BlameCommitFileLnum(getline(a:count))\n        if len(blame[0])\n          let expanded = blame[0]\n        endif\n      endif\n    endif\n    let full = s:Generate(expanded, dir)\n    let commit = ''\n    let ref = ''\n    let forbid_ref_as_commit = 0\n    if full =~# '^fugitive:'\n      let [dir, commit, path] = s:DirCommitFile(full)\n      if commit =~# '^\\d\\=$'\n        let commit = ''\n        let type = path =~# '^/\\=$' ? 'tree' : 'blob'\n      else\n        let ref_match = matchlist(expanded, '^\\(@{\\@!\\|[^:~^@]\\+\\)\\(:\\%(//\\)\\@!\\|[~^@]\\|$\\)')\n        let ref = get(ref_match, 1, '')\n        let forbid_ref_as_commit = ref =~# '^@\\=$' || ref_match[2] !~# '^:\\=$'\n        if empty(path) && !forbid_ref_as_commit\n          let type = 'ref'\n        else\n          let type = s:ChompDefault(empty(path) ? 'commit': 'blob',\n                \\ ['cat-file', '-t', commit . substitute(path, '^/', ':', '')], dir)\n        endif\n      endif\n      let path = path[1:-1]\n    elseif !empty(s:Tree(dir))\n      let relevant_dir = FugitiveExtractGitDir(full)\n      if !empty(relevant_dir)\n        let dir = relevant_dir\n      endif\n      let path = fugitive#Path(full, '/', dir)[1:-1]\n      if empty(path) || isdirectory(full)\n        let type = 'tree'\n      else\n        let type = 'blob'\n      endif\n    else\n      let path = '.git/' . full[strlen(dir)+1:-1]\n      let type = ''\n    endif\n    exe s:DirCheck(dir)\n    if path =~# '^\\.git/'\n      let ref = matchstr(path, '^.git/\\zs\\%(refs/[^/]\\+/[^/].*\\|\\w*HEAD\\)$')\n      let type = empty(ref) ? 'root': 'ref'\n      let path = ''\n    endif\n    if empty(ref) || ref ==# 'HEAD' || ref ==# '@'\n      let ref = fugitive#Head(-1, dir)\n    endif\n    if ref =~# '^\\x\\{40,\\}$'\n      let ref = ''\n    elseif !empty(ref) && ref !~# '^refs/'\n      let ref = FugitiveExecute(['rev-parse', '--symbolic-full-name', ref], dir).stdout[0]\n      if ref !~# '^refs/'\n        let ref = ''\n      endif\n    endif\n\n    if !exists('l:config') || s:Dir(config) !=# dir\n      let config = fugitive#Config(dir)\n    endif\n    let merge = ''\n    if !empty(remote) && ref =~# '^refs/remotes/[^/]\\+/[^/]\\|^refs/heads/[^/]'\n      let merge = matchstr(ref, '^refs/\\%(heads/\\|remotes/[^/]\\+/\\)\\zs.\\+')\n      let ref = 'refs/heads/' . merge\n    elseif ref =~# '^refs/remotes/[^/]\\+/[^/]'\n      let remote = matchstr(ref, '^refs/remotes/\\zs[^/]\\+')\n      let merge = matchstr(ref, '^refs/remotes/[^/]\\+/\\zs.\\+')\n      let ref = 'refs/heads/' . merge\n    elseif ref =~# '^refs/heads/[^/]'\n      let merge = strpart(ref, 11)\n      let r = FugitiveConfigGet('branch.' . merge . '.remote', config)\n      let m = FugitiveConfigGet('branch.' . merge . '.merge', config)[11:-1]\n      if r ==# '.' && !empty(m)\n        let r2 = FugitiveConfigGet('branch.'.m.'.remote', config)\n        if r2 !~# '^\\.\\=$'\n          let r = r2\n          let m = FugitiveConfigGet('branch.'.m.'.merge', config)[11:-1]\n        endif\n      endif\n      if r !~# '^\\.\\=$'\n        let remote = r\n      endif\n      if !empty(remote)\n        let remote_ref = 'refs/remotes/' . remote . '/' . merge\n        if FugitiveConfigGet('push.default', config) ==# 'upstream' ||\n              \\ !filereadable(FugitiveFind('.git/' . remote_ref, dir)) && empty(s:ChompDefault('', ['rev-parse', '--verify', remote_ref, '--'], dir))\n          let merge = m\n          let ref = 'refs/heads/' . merge\n        endif\n      endif\n    endif\n\n    if empty(remote) || remote ==# '.'\n      let remote = s:RemoteDefault(config)\n    endif\n    if empty(merge) || empty(remote)\n      let provider_ref = ref\n    else\n      let provider_ref = 'refs/remotes/' . remote . '/' . merge\n    endif\n    if forbid_ref_as_commit || a:count >= 0\n      let ref = ''\n      if type ==# 'ref'\n        let type = 'commit'\n      endif\n    elseif type ==# 'ref' && ref =~# '^refs/\\%(heads\\|tags\\)/[^/]'\n        let commit = matchstr(ref, '^\\Crefs/\\%(heads\\|tags\\)/\\zs.*')\n    endif\n\n    let line1 = a:count > 0 && type ==# 'blob' ? a:line1 : 0\n    let line2 = a:count > 0 && type ==# 'blob' ? a:count : 0\n    if empty(commit) && type =~# '^\\%(tree\\|blob\\)$'\n      if a:count < 0\n        let commit = matchstr(ref, '^\\Crefs/\\%(heads\\|tags\\)/\\zs.*')\n      elseif len(provider_ref)\n        let owner = s:Owner(@%, dir)\n        let commit = s:ChompDefault('', ['merge-base', provider_ref, empty(owner) ? '@' : owner, '--'], dir)\n        if line2 > 0 && empty(arg) && commit =~# '^\\x\\{40,\\}$' && type ==# 'blob'\n          let blame_list = tempname()\n          call writefile([commit, ''], blame_list, 'b')\n          let blame_cmd = ['-c', 'blame.coloring=none', 'blame', '-L', line1.','.line2, '-S', blame_list, '-s', '--show-number']\n          if !&l:modified || has_key(result, 'origin_bufnr')\n            let [blame, exec_error] = s:LinesError(blame_cmd + ['./' . path], dir)\n          else\n            let blame_in = tempname()\n            silent exe 'noautocmd keepalt %write' blame_in\n            let [blame, exec_error] = s:LinesError(blame_cmd + ['--contents', blame_in, './' . path], dir)\n            call delete(blame_in)\n          endif\n          call delete(blame_list)\n          if !exec_error\n            let blame_regex = '^\\^\\x\\+\\s\\+\\zs\\d\\+\\ze\\s'\n            if get(blame, 0) =~# blame_regex && get(blame, -1) =~# blame_regex\n              let line1 = +matchstr(blame[0], blame_regex)\n              let line2 = +matchstr(blame[-1], blame_regex)\n            else\n              throw \"fugitive: can't browse to unpushed change\"\n            endif\n          endif\n        endif\n      endif\n      if empty(commit)\n        let commit = fugitive#RevParse(empty(ref) ? 'HEAD' : ref, dir)\n      endif\n    endif\n\n    if remote =~# ':'\n      let remote_url = remote\n    else\n      let remote_url = fugitive#RemoteUrl(remote, config)\n    endif\n    let raw = empty(remote_url) ? remote : remote_url\n    let git_dir = s:GitDir(dir)\n\n    let opts = {\n          \\ 'git_dir': git_dir,\n          \\ 'repo': {'git_dir': git_dir},\n          \\ 'remote': raw,\n          \\ 'remote_name': remote,\n          \\ 'commit': s:UrlEncode(commit),\n          \\ 'path': substitute(s:UrlEncode(path), '%20', ' ', 'g'),\n          \\ 'type': type,\n          \\ 'line1': line1,\n          \\ 'line2': line2}\n\n    if empty(path)\n      if type ==# 'ref' && ref =~# '^refs/'\n        let opts.path = '.git/' . s:UrlEncode(ref)\n        let opts.type = ''\n      elseif type ==# 'root'\n        let opts.path ='.git/index'\n        let opts.type = ''\n      endif\n    elseif type ==# 'tree' && !empty(path)\n      let opts.path = s:sub(opts.path, '/\\=$', '/')\n    endif\n\n    for l:.Handler in get(g:, 'fugitive_browse_handlers', [])\n      let l:.url = call(Handler, [copy(opts)])\n      if type(url) == type('') && url =~# '://'\n        return s:BrowserOpen(url, a:mods, a:bang)\n      endif\n    endfor\n\n    if !empty(remote_url)\n      return 'echoerr ' . string(\"fugitive: no GBrowse handler installed for '\".remote_url.\"'\")\n    else\n      return 'echoerr ' . string(\"fugitive: could not find remote named '\".remote.\"'\")\n    endif\n  catch /^fugitive:/\n    return 'echoerr ' . string(v:exception)\n  endtry\nendfunction\n\nfunction! s:RemoteRefToLocalRef(repo, remote_url, ref_path) abort\n  let ref_path = substitute(a:ref_path, ':', '/', '')\n  let rev = ''\n  if ref_path =~# '^\\x\\{40,\\}\\%(/\\|$\\)'\n    let rev = substitute(ref_path, '/', ':', '')\n  elseif ref_path =~# '^[^:/^~]\\+'\n    let first_component = matchstr(ref_path, '^[^:/^~]\\+')\n    let lines = fugitive#Execute(['ls-remote', a:remote_url, first_component, first_component . '/*'], a:repo).stdout[0:-2]\n    for line in lines\n      let full = matchstr(line, \"\\t\\\\zs.*\")\n      for candidate in [full, matchstr(full, '^refs/\\w\\+/\\zs.*')]\n        if candidate ==# first_component || strpart(ref_path . '/', 0, len(candidate) + 1) ==# candidate . '/'\n          let rev = matchstr(line, '^\\x\\+') . substitute(strpart(ref_path, len(candidate)), '/', ':', '')\n        endif\n      endfor\n    endfor\n  endif\n  if empty(rev)\n    return ''\n  endif\n  let commitish = matchstr(rev, '^[^:^~]*')\n  let rev_parse = fugitive#Execute(['rev-parse', '--verify', commitish], a:repo)\n  if rev_parse.exit_status\n    if fugitive#Execute(['fetch', remote_url, commitish], a:repo).exit_status\n      return ''\n    endif\n    let rev_parse = fugitive#Execute(['rev-parse', '--verify', commitish], a:repo)\n  endif\n  if rev_parse.exit_status\n    return ''\n  endif\n  return rev_parse.stdout[0] . matchstr(rev, ':.*')\nendfunction\n\nfunction! fugitive#ResolveUrl(target, ...) abort\n  let repo = call('s:Dir', a:000)\n  let origins = get(g:, 'fugitive_url_origins', {})\n  let prefix = substitute(s:Slash(a:target), '#.*', '', '')\n  while prefix =~# '://'\n    let extracted = FugitiveExtractGitDir(expand(get(origins, prefix, '')))\n    if !empty(extracted)\n      let repo = s:Dir(extracted)\n      break\n    endif\n    let prefix = matchstr(prefix, '.*\\ze/')\n  endwhile\n  let git_dir = s:GitDir(repo)\n  for remote_name in keys(FugitiveConfigGetRegexp('^remote\\.\\zs.*\\ze\\.url$', repo))\n    let remote_url = fugitive#RemoteUrl(remote_name, repo)\n    for [no_anchor; variant] in [[1, 'commit'], [1, 'tree'], [1, 'tree', 1], [1, 'blob', 1], [0, 'blob', 1, '1`line1`', '1`line1`'], [0, 'blob', 1, '1`line1`', '2`line2`']]\n      let handler_opts = {\n            \\ 'git_dir': git_dir,\n            \\ 'repo': {'git_dir': git_dir},\n            \\ 'remote': remote_url,\n            \\ 'remote_name': remote_name,\n            \\ 'commit': '1`commit`',\n            \\ 'type': get(variant, 0),\n            \\ 'path': get(variant, 1) ? '1`path`' : '',\n            \\ 'line1': get(variant, 2),\n            \\ 'line2': get(variant, 3)}\n      let url = ''\n      for l:.Handler in get(g:, 'fugitive_browse_handlers', [])\n        let l:.url = call(Handler, [copy(handler_opts)])\n        if type(url) == type('') && url =~# '://'\n          break\n        endif\n      endfor\n      if type(url) != type('') || url !~# '://'\n        continue\n      endif\n      let keys = split(substitute(url, '\\d`\\(\\w\\+`\\)\\|.', '\\1', 'g'), '`')\n      let pattern = substitute(url, '\\d`\\w\\+`\\|[][^$.*\\~]', '\\=len(submatch(0)) == 1 ? \"\\\\\" . submatch(0) : \"\\\\([^#?&;]\\\\{-\\\\}\\\\)\"', 'g')\n      let pattern = '^' . substitute(pattern, '^https\\=:', 'https\\\\=:', '') . '$'\n      let target = s:Slash(no_anchor ? substitute(a:target, '#.*', '', '') : a:target)\n      let values = matchlist(s:Slash(a:target), pattern)[1:-1]\n      if empty(values)\n        continue\n      endif\n      let kvs = {}\n      for i in range(len(keys))\n        let kvs[keys[i]] = values[i]\n      endfor\n      if has_key(kvs, 'commit') && has_key(kvs, 'path')\n        let ref_path = kvs.commit . '/' . kvs.path\n      elseif has_key(kvs, 'commit') && variant[0] ==# 'tree'\n        let ref_path = kvs.commit . '/'\n      elseif has_key(kvs, 'commit')\n        let ref_path = kvs.commit\n      else\n        continue\n      endif\n      let rev = s:RemoteRefToLocalRef(repo, remote_url, fugitive#UrlDecode(ref_path))\n      return [fugitive#Find(rev, repo), empty(rev) ? 0 : +get(kvs, 'line1')]\n    endfor\n  endfor\n  return ['', 0]\nendfunction\n\nfunction! s:ResolveUrl(target, ...) abort\n  try\n    let [url, lnum] = call('fugitive#ResolveUrl', [a:target] + a:000)\n    if !empty(url)\n      return [url, lnum]\n    endif\n  catch\n  endtry\n  return [substitute(a:target, '#.*', '', ''), 0]\nendfunction\n\n\" Section: Maps\n\nlet s:ref_header = '\\%(Merge\\|Rebase\\|Upstream\\|Pull\\|Push\\)'\n\nnnoremap <SID>: :<C-U><C-R>=v:count ? v:count : ''<CR>\nfunction! fugitive#MapCfile(...) abort\n  exe 'cnoremap <buffer> <expr> <Plug><cfile>' (a:0 ? a:1 : 'fugitive#Cfile()')\n  let b:undo_ftplugin = get(b:, 'undo_ftplugin', 'exe') . '|sil! exe \"cunmap <buffer> <Plug><cfile>\"'\n  if !exists('g:fugitive_no_maps')\n    call s:Map('n', 'gf',          '<SID>:find <Plug><cfile><CR>', '<silent><unique>', 1)\n    call s:Map('n', '<C-W>f',     '<SID>:sfind <Plug><cfile><CR>', '<silent><unique>', 1)\n    call s:Map('n', '<C-W><C-F>', '<SID>:sfind <Plug><cfile><CR>', '<silent><unique>', 1)\n    call s:Map('n', '<C-W>gf',  '<SID>:tabfind <Plug><cfile><CR>', '<silent><unique>', 1)\n    call s:Map('c', '<C-R><C-F>', '<Plug><cfile>', '<unique>', 1)\n  endif\nendfunction\n\nfunction! s:ContainingCommit() abort\n  let commit = s:Owner(@%)\n  return empty(commit) ? '@' : commit\nendfunction\n\nfunction! s:SquashArgument(...) abort\n  if &filetype == 'fugitive'\n    let commit = matchstr(getline('.'), '^\\%(\\%(\\x\\x\\x\\)\\@!\\l\\+\\s\\+\\)\\=\\zs[0-9a-f]\\{4,\\}\\ze \\|^' . s:ref_header . ': \\zs\\S\\+')\n  elseif has_key(s:temp_files, s:cpath(expand('%:p')))\n    let commit = matchstr(getline('.'), '\\S\\@<!\\x\\{4,\\}\\S\\@!')\n  else\n    let commit = s:Owner(@%)\n  endif\n  return len(commit) && a:0 ? printf(a:1, commit) : commit\nendfunction\n\nfunction! s:RebaseArgument() abort\n  return s:SquashArgument(' %s^')\nendfunction\n\nfunction! s:NavigateUp(count) abort\n  let rev = substitute(s:DirRev(@%)[1], '^$', ':', 'g')\n  let c = a:count\n  while c\n    if rev =~# ':.*/.'\n      let rev = matchstr(rev, '.*\\ze/.\\+', '')\n    elseif rev =~# '.:.'\n      let rev = matchstr(rev, '^.[^:]*:')\n    elseif rev =~# '^:'\n      let rev = '@^{}'\n    elseif rev =~# ':$'\n      let rev = rev[0:-2]\n    else\n      return rev.'~'.c\n    endif\n    let c -= 1\n  endwhile\n  return rev\nendfunction\n\nfunction! s:ParseDiffHeader(str) abort\n  let list = matchlist(a:str, '\\Cdiff --git \\(\"\\=\\w/.*\\|/dev/null\\) \\(\"\\=\\w/.*\\|/dev/null\\)$')\n  if empty(list)\n    let list = matchlist(a:str, '\\Cdiff --git \\(\"\\=[^/].*\\|/dev/null\\) \\(\"\\=[^/].*\\|/dev/null\\)$')\n  endif\n  return [fugitive#Unquote(get(list, 1, '')), fugitive#Unquote(get(list, 2, ''))]\nendfunction\n\nfunction! s:HunkPosition(lnum) abort\n  let lnum = a:lnum + get({'@': 1, '\\': -1}, getline(a:lnum)[0], 0)\n  let offsets = {' ': -1, '+': 0, '-': 0}\n  let sigil = getline(lnum)[0]\n  let line_char = sigil\n  while has_key(offsets, line_char)\n    let offsets[line_char] += 1\n    let lnum -= 1\n    let line_char = getline(lnum)[0]\n  endwhile\n  let starts = matchlist(getline(lnum), '^@@\\+[ 0-9,-]* -\\(\\d\\+\\)\\%(,\\d\\+\\)\\= +\\(\\d\\+\\)[ ,]')\n  if empty(starts)\n    return [0, 0, 0]\n  endif\n  return [lnum,\n        \\ sigil ==# '+' ? 0 : starts[1] + offsets[' '] + offsets['-'],\n        \\ sigil ==# '-' ? 0 : starts[2] + offsets[' '] + offsets['+']]\nendfunction\n\nfunction! s:MapMotion(lhs, rhs) abort\n  let maps = [\n        \\ s:Map('n', a:lhs, \":<C-U>\" . a:rhs . \"<CR>\", \"<silent>\"),\n        \\ s:Map('o', a:lhs, \":<C-U>\" . a:rhs . \"<CR>\", \"<silent>\"),\n        \\ s:Map('x', a:lhs, \":<C-U>exe 'normal! gv'<Bar>\" . a:rhs . \"<CR>\", \"<silent>\")]\n  call filter(maps, '!empty(v:val)')\n  return join(maps, '|')\nendfunction\n\nfunction! s:MapGitOps(is_ftplugin) abort\n  let ft = a:is_ftplugin\n  if &modifiable\n    return ''\n  endif\n  exe s:Map('n', 'c<Space>', ':Git commit<Space>', '', ft)\n  exe s:Map('n', 'c<CR>', ':Git commit<CR>', '', ft)\n  exe s:Map('n', 'cv<Space>', ':tab Git commit -v<Space>', '', ft)\n  exe s:Map('n', 'cv<CR>', ':tab Git commit -v<CR>', '', ft)\n  exe s:Map('n', 'ca', ':<C-U>Git commit --amend<CR>', '<silent>', ft)\n  exe s:Map('n', 'cc', ':<C-U>Git commit<CR>', '<silent>', ft)\n  exe s:Map('n', 'ce', ':<C-U>Git commit --amend --no-edit<CR>', '<silent>', ft)\n  exe s:Map('n', 'cw', ':<C-U>Git commit --amend --only<CR>', '<silent>', ft)\n  exe s:Map('n', 'cW', ':<C-U>Git commit --fixup=reword:<C-R>=<SID>SquashArgument()<CR>', '', ft)\n  exe s:Map('n', 'cva', ':<C-U>tab Git commit -v --amend<CR>', '<silent>', ft)\n  exe s:Map('n', 'cvc', ':<C-U>tab Git commit -v<CR>', '<silent>', ft)\n  exe s:Map('n', 'cRa', ':<C-U>Git commit --reset-author --amend<CR>', '<silent>', ft)\n  exe s:Map('n', 'cRe', ':<C-U>Git commit --reset-author --amend --no-edit<CR>', '<silent>', ft)\n  exe s:Map('n', 'cRw', ':<C-U>Git commit --reset-author --amend --only<CR>', '<silent>', ft)\n  exe s:Map('n', 'cf', ':<C-U>Git commit --fixup=<C-R>=<SID>SquashArgument()<CR>', '', ft)\n  exe s:Map('n', 'cF', ':<C-U><Bar>Git -c sequence.editor=true rebase --interactive --autosquash<C-R>=<SID>RebaseArgument()<CR><Home>Git commit --fixup=<C-R>=<SID>SquashArgument()<CR>', '', ft)\n  exe s:Map('n', 'cs', ':<C-U>Git commit --no-edit --squash=<C-R>=<SID>SquashArgument()<CR>', '', ft)\n  exe s:Map('n', 'cS', ':<C-U><Bar>Git -c sequence.editor=true rebase --interactive --autosquash<C-R>=<SID>RebaseArgument()<CR><Home>Git commit --no-edit --squash=<C-R>=<SID>SquashArgument()<CR>', '', ft)\n  exe s:Map('n', 'cn', ':<C-U>Git commit --edit --squash=<C-R>=<SID>SquashArgument()<CR>', '', ft)\n  exe s:Map('n', 'cA', ':<C-U>echoerr \"Use cn\"<CR>', '<silent><unique>', ft)\n  exe s:Map('n', 'c?', ':<C-U>help fugitive_c<CR>', '<silent>', ft)\n\n  exe s:Map('n', 'cr<Space>', ':Git revert<Space>', '', ft)\n  exe s:Map('n', 'cr<CR>', ':Git revert<CR>', '', ft)\n  exe s:Map('n', 'crc', ':<C-U>Git revert <C-R>=<SID>SquashArgument()<CR><CR>', '<silent>', ft)\n  exe s:Map('n', 'crn', ':<C-U>Git revert --no-commit <C-R>=<SID>SquashArgument()<CR><CR>', '<silent>', ft)\n  exe s:Map('n', 'cr?', ':<C-U>help fugitive_cr<CR>', '<silent>', ft)\n\n  exe s:Map('n', 'cm<Space>', ':Git merge<Space>', '', ft)\n  exe s:Map('n', 'cm<CR>', ':Git merge<CR>', '', ft)\n  exe s:Map('n', 'cmt', ':Git mergetool', '', ft)\n  exe s:Map('n', 'cm?', ':<C-U>help fugitive_cm<CR>', '<silent>', ft)\n\n  exe s:Map('n', 'cz<Space>', ':Git stash<Space>', '', ft)\n  exe s:Map('n', 'cz<CR>', ':Git stash<CR>', '', ft)\n  exe s:Map('n', 'cza', ':<C-U>Git stash apply --quiet --index stash@{<C-R>=v:count<CR>}<CR>', '', ft)\n  exe s:Map('n', 'czA', ':<C-U>Git stash apply --quiet stash@{<C-R>=v:count<CR>}<CR>', '', ft)\n  exe s:Map('n', 'czp', ':<C-U>Git stash pop --quiet --index stash@{<C-R>=v:count<CR>}<CR>', '', ft)\n  exe s:Map('n', 'czP', ':<C-U>Git stash pop --quiet stash@{<C-R>=v:count<CR>}<CR>', '', ft)\n  exe s:Map('n', 'czs', ':<C-U>Git stash push --staged<CR>', '', ft)\n  exe s:Map('n', 'czv', ':<C-U>exe \"Gedit\" fugitive#RevParse(\"stash@{\" . v:count . \"}\")<CR>', '<silent>', ft)\n  exe s:Map('n', 'czw', ':<C-U>Git stash push --keep-index<C-R>=v:count > 1 ? \" --all\" : v:count ? \" --include-untracked\" : \"\"<CR><CR>', '', ft)\n  exe s:Map('n', 'czz', ':<C-U>Git stash push <C-R>=v:count > 1 ? \" --all\" : v:count ? \" --include-untracked\" : \"\"<CR><CR>', '', ft)\n  exe s:Map('n', 'cz?', ':<C-U>help fugitive_cz<CR>', '<silent>', ft)\n\n  exe s:Map('n', 'co<Space>', ':Git checkout<Space>', '', ft)\n  exe s:Map('n', 'co<CR>', ':Git checkout<CR>', '', ft)\n  exe s:Map('n', 'coo', ':<C-U>Git checkout <C-R>=substitute(<SID>SquashArgument(),\"^$\",get(<SID>TempState(),\"filetype\",\"\") ==# \"git\" ? expand(\"<cfile>\") : \"\",\"\")<CR> --<CR>', '', ft)\n  exe s:Map('n', 'co?', ':<C-U>help fugitive_co<CR>', '<silent>', ft)\n\n  exe s:Map('n', 'cb<Space>', ':Git branch<Space>', '', ft)\n  exe s:Map('n', 'cb<CR>', ':Git branch<CR>', '', ft)\n  exe s:Map('n', 'cb?', ':<C-U>help fugitive_cb<CR>', '<silent>', ft)\n\n  exe s:Map('n', 'r<Space>', ':Git rebase<Space>', '', ft)\n  exe s:Map('n', 'r<CR>', ':Git rebase<CR>', '', ft)\n  exe s:Map('n', 'ri', ':<C-U>Git rebase --interactive<C-R>=<SID>RebaseArgument()<CR><CR>', '<silent>', ft)\n  exe s:Map('n', 'rf', ':<C-U>Git -c sequence.editor=true rebase --interactive --autosquash<C-R>=<SID>RebaseArgument()<CR><CR>', '<silent>', ft)\n  exe s:Map('n', 'ru', ':<C-U>Git rebase --interactive @{upstream}<CR>', '<silent>', ft)\n  exe s:Map('n', 'rp', ':<C-U>Git rebase --interactive @{push}<CR>', '<silent>', ft)\n  exe s:Map('n', 'rw', ':<C-U>Git rebase --interactive<C-R>=<SID>RebaseArgument()<CR><Bar>s/^pick/reword/e<CR>', '<silent>', ft)\n  exe s:Map('n', 'rm', ':<C-U>Git rebase --interactive<C-R>=<SID>RebaseArgument()<CR><Bar>s/^pick/edit/e<CR>', '<silent>', ft)\n  exe s:Map('n', 'rd', ':<C-U>Git rebase --interactive<C-R>=<SID>RebaseArgument()<CR><Bar>s/^pick/drop/e<CR>', '<silent>', ft)\n  exe s:Map('n', 'rk', ':<C-U>Git rebase --interactive<C-R>=<SID>RebaseArgument()<CR><Bar>s/^pick/drop/e<CR>', '<silent>', ft)\n  exe s:Map('n', 'rx', ':<C-U>Git rebase --interactive<C-R>=<SID>RebaseArgument()<CR><Bar>s/^pick/drop/e<CR>', '<silent>', ft)\n  exe s:Map('n', 'rr', ':<C-U>Git rebase --continue<CR>', '<silent>', ft)\n  exe s:Map('n', 'rs', ':<C-U>Git rebase --skip<CR>', '<silent>', ft)\n  exe s:Map('n', 're', ':<C-U>Git rebase --edit-todo<CR>', '<silent>', ft)\n  exe s:Map('n', 'ra', ':<C-U>Git rebase --abort<CR>', '<silent>', ft)\n  exe s:Map('n', 'r?', ':<C-U>help fugitive_r<CR>', '<silent>', ft)\nendfunction\n\nfunction! fugitive#MapJumps(...) abort\n  if !&modifiable\n    if get(b:, 'fugitive_type', '') ==# 'blob'\n      let blame_tail = '<C-R>=v:count ? \" --reverse\" : \"\"<CR><CR>'\n      exe s:Map('n', '<2-LeftMouse>', ':<C-U>0,1Git ++curwin blame' . blame_tail, '<silent>')\n      exe s:Map('n', '<CR>', ':<C-U>0,1Git ++curwin blame' . blame_tail, '<silent>')\n      exe s:Map('n', 'o',    ':<C-U>0,1Git blame' . blame_tail, '<silent>')\n      exe s:Map('n', 'p',    ':<C-U>0,1Git! blame' . blame_tail, '<silent>')\n      if has('patch-7.4.1898')\n        exe s:Map('n', 'gO',   ':<C-U>vertical 0,1Git blame' . blame_tail, '<silent>')\n        exe s:Map('n', 'O',    ':<C-U>tab 0,1Git blame' . blame_tail, '<silent>')\n      else\n        exe s:Map('n', 'gO',   ':<C-U>0,4Git blame' . blame_tail, '<silent>')\n        exe s:Map('n', 'O',    ':<C-U>0,5Git blame' . blame_tail, '<silent>')\n      endif\n\n      call s:Map('n', 'D', \":echoerr 'fugitive: D has been removed in favor of dd'<CR>\", '<silent><unique>')\n      call s:Map('n', 'dd', \":<C-U>call fugitive#DiffClose()<Bar>keepalt Gdiffsplit!<CR>\", '<silent>')\n      call s:Map('n', 'dh', \":<C-U>call fugitive#DiffClose()<Bar>keepalt Ghdiffsplit!<CR>\", '<silent>')\n      call s:Map('n', 'ds', \":<C-U>call fugitive#DiffClose()<Bar>keepalt Ghdiffsplit!<CR>\", '<silent>')\n      call s:Map('n', 'dv', \":<C-U>call fugitive#DiffClose()<Bar>keepalt Gvdiffsplit!<CR>\", '<silent>')\n      call s:Map('n', 'd?', \":<C-U>help fugitive_d<CR>\", '<silent>')\n\n    else\n      call s:Map('n', '<2-LeftMouse>', ':<C-U>exe <SID>GF(\"edit\")<CR>', '<silent>')\n      call s:Map('n', '<CR>', ':<C-U>exe <SID>GF(\"edit\")<CR>', '<silent>')\n      call s:Map('n', 'o',    ':<C-U>exe <SID>GF(\"split\")<CR>', '<silent>')\n      call s:Map('n', 'gO',   ':<C-U>exe <SID>GF(\"vsplit\")<CR>', '<silent>')\n      call s:Map('n', 'O',    ':<C-U>exe <SID>GF(\"tabedit\")<CR>', '<silent>')\n      call s:Map('n', 'p',    ':<C-U>exe <SID>GF(\"pedit\")<CR>', '<silent>')\n\n      if !exists('g:fugitive_no_maps')\n        call s:Map('n', '<C-P>', ':exe <SID>PreviousItem(v:count1)<Bar>echohl WarningMsg<Bar>echo \"CTRL-P is deprecated in favor of (\"<Bar>echohl NONE<CR>', '<unique>')\n        call s:Map('n', '<C-N>', ':exe <SID>NextItem(v:count1)<Bar>echohl WarningMsg<Bar>echo \"CTRL-N is deprecated in favor of )\"<Bar>echohl NONE<CR>', '<unique>')\n      endif\n      call s:MapMotion('(', 'exe <SID>PreviousItem(v:count1)')\n      call s:MapMotion(')', 'exe <SID>NextItem(v:count1)')\n      call s:MapMotion('K', 'exe <SID>PreviousHunk(v:count1)')\n      call s:MapMotion('J', 'exe <SID>NextHunk(v:count1)')\n      call s:MapMotion('[c', 'exe <SID>PreviousHunk(v:count1)')\n      call s:MapMotion(']c', 'exe <SID>NextHunk(v:count1)')\n      call s:MapMotion('[/', 'exe <SID>PreviousFile(v:count1)')\n      call s:MapMotion(']/', 'exe <SID>NextFile(v:count1)')\n      call s:MapMotion('[m', 'exe <SID>PreviousFile(v:count1)')\n      call s:MapMotion(']m', 'exe <SID>NextFile(v:count1)')\n      call s:MapMotion('[[', 'exe <SID>PreviousSection(v:count1)')\n      call s:MapMotion(']]', 'exe <SID>NextSection(v:count1)')\n      call s:MapMotion('[]', 'exe <SID>PreviousSectionEnd(v:count1)')\n      call s:MapMotion('][', 'exe <SID>NextSectionEnd(v:count1)')\n      call s:Map('no', '*', '<SID>PatchSearchExpr(0)', '<expr>')\n      call s:Map('no', '#', '<SID>PatchSearchExpr(1)', '<expr>')\n    endif\n    call s:Map('n', 'S',    ':<C-U>echoerr \"Use gO\"<CR>', '<silent><unique>')\n    call s:Map('n', 'dq', \":<C-U>call fugitive#DiffClose()<CR>\", '<silent>')\n    call s:Map('n', '-', \":<C-U>exe 'Gedit ' . <SID>fnameescape(<SID>NavigateUp(v:count1))<Bar> if getline(1) =~# '^tree \\x\\{40,\\}$' && empty(getline(2))<Bar>call search('^'.escape(expand('#:t'),'.*[]~\\').'/\\=$','wc')<Bar>endif<CR>\", '<silent>')\n    call s:Map('n', 'P',     \":<C-U>if !v:count<Bar>echoerr 'Use ~ (or provide a count)'<Bar>else<Bar>exe 'Gedit ' . <SID>fnameescape(<SID>ContainingCommit().'^'.v:count1.<SID>Relative(':'))<Bar>endif<CR>\", '<silent>')\n    call s:Map('n', '~',     \":<C-U>exe 'Gedit ' . <SID>fnameescape(<SID>ContainingCommit().'~'.v:count1.<SID>Relative(':'))<CR>\", '<silent>')\n    call s:Map('n', 'C',     \":<C-U>exe 'Gedit ' . <SID>fnameescape(<SID>ContainingCommit())<CR>\", '<silent>')\n    call s:Map('n', 'cp',    \":<C-U>echoerr 'Use gC'<CR>\", '<silent><unique>')\n    call s:Map('n', 'gC',    \":<C-U>exe 'Gpedit ' . <SID>fnameescape(<SID>ContainingCommit())<CR>\", '<silent>')\n    call s:Map('n', 'gc',    \":<C-U>exe 'Gpedit ' . <SID>fnameescape(<SID>ContainingCommit())<CR>\", '<silent>')\n    call s:Map('n', 'gi',    \":<C-U>exe 'Gsplit' (v:count ? '.gitignore' : '.git/info/exclude')<CR>\", '<silent>')\n    call s:Map('x', 'gi',    \":<C-U>exe 'Gsplit' (v:count ? '.gitignore' : '.git/info/exclude')<CR>\", '<silent>')\n\n    call s:Map('n', '.',     \":<C-U> <C-R>=<SID>fnameescape(fugitive#Real(@%))<CR><Home>\")\n    call s:Map('x', '.',     \":<C-U> <C-R>=<SID>fnameescape(fugitive#Real(@%))<CR><Home>\")\n    call s:Map('n', 'g?',    \":<C-U>help fugitive-maps<CR>\", '<silent>')\n    call s:Map('n', '<F1>',  \":<C-U>help fugitive-maps<CR>\", '<silent>')\n  endif\n\n  let old_browsex = maparg('<Plug>NetrwBrowseX', 'n')\n  let new_browsex = substitute(old_browsex, '\\Cnetrw#CheckIfRemote(\\%(netrw#GX()\\)\\=)', '0', 'g')\n  let new_browsex = substitute(new_browsex, 'netrw#GX()\\|expand((exists(\"g:netrw_gx\")? g:netrw_gx : ''<cfile>''))', 'fugitive#GX()', 'g')\n  if new_browsex !=# old_browsex\n    exe 'nnoremap <silent> <buffer> <Plug>NetrwBrowseX' new_browsex\n  endif\n  call s:MapGitOps(0)\nendfunction\n\nfunction! fugitive#GX() abort\n  try\n    let results = &filetype ==# 'fugitive' ? s:CfilePorcelain() : &filetype ==# 'git' ? s:cfile() : []\n    if len(results) && len(results[0])\n      return FugitiveReal(s:Generate(results[0]))\n    endif\n  catch /^fugitive:/\n  endtry\n  return expand(get(g:, 'netrw_gx', expand('<cfile>')))\nendfunction\n\nfunction! s:CfilePorcelain(...) abort\n  let tree = s:Tree()\n  if empty(tree)\n    return ['']\n  endif\n  let lead = s:cpath(tree, getcwd()) ? './' : tree . '/'\n  let info = s:StageInfo()\n  let line = getline('.')\n  if len(info.sigil) && len(info.section) && len(info.paths)\n    if info.section ==# 'Unstaged' && info.sigil !=# '-'\n      return [lead . info.relative[0], info.offset, 'normal!zv']\n    elseif info.section ==# 'Staged' && info.sigil ==# '-'\n      return ['@:' . info.relative[0], info.offset, 'normal!zv']\n    else\n      return [':0:' . info.relative[0], info.offset, 'normal!zv']\n    endif\n  elseif len(info.paths)\n    return [lead . info.relative[0]]\n  elseif len(info.commit)\n    return [info.commit]\n  elseif line =~# '^' . s:ref_header . ': \\|^Head: '\n    return [matchstr(line, ' \\zs.*')]\n  else\n    return ['']\n  endif\nendfunction\n\nfunction! fugitive#PorcelainCfile() abort\n  let file = fugitive#Find(s:CfilePorcelain()[0])\n  return empty(file) ? fugitive#Cfile() : s:fnameescape(file)\nendfunction\n\nfunction! s:StatusCfile(...) abort\n  let tree = s:Tree()\n  if empty(tree)\n    return []\n  endif\n  let lead = s:cpath(tree, getcwd()) ? './' : tree . '/'\n  if getline('.') =~# '^.\\=\\trenamed:.* -> '\n    return [lead . matchstr(getline('.'),' -> \\zs.*')]\n  elseif getline('.') =~# '^.\\=\\t\\(\\k\\| \\)\\+\\p\\?: *.'\n    return [lead . matchstr(getline('.'),': *\\zs.\\{-\\}\\ze\\%( ([^()[:digit:]]\\+)\\)\\=$')]\n  elseif getline('.') =~# '^.\\=\\t.'\n    return [lead . matchstr(getline('.'),'\\t\\zs.*')]\n  elseif getline('.') =~# ': needs merge$'\n    return [lead . matchstr(getline('.'),'.*\\ze: needs merge$')]\n  elseif getline('.') =~# '^\\%(. \\)\\=Not currently on any branch.$'\n    return ['HEAD']\n  elseif getline('.') =~# '^\\%(. \\)\\=On branch '\n    return ['refs/heads/'.getline('.')[12:]]\n  elseif getline('.') =~# \"^\\\\%(. \\\\)\\=Your branch .*'\"\n    return [matchstr(getline('.'),\"'\\\\zs\\\\S\\\\+\\\\ze'\")]\n  else\n    return []\n  endif\nendfunction\n\nfunction! fugitive#MessageCfile() abort\n  let file = fugitive#Find(get(s:StatusCfile(), 0, ''))\n  return empty(file) ? fugitive#Cfile() : s:fnameescape(file)\nendfunction\n\nfunction! s:BranchCfile(result) abort\n  return matchstr(getline('.'), '^. \\zs\\S\\+')\nendfunction\n\nlet s:diff_header_pattern = '^diff --git \\%(\"\\=[abciow12]/.*\\|/dev/null\\) \\%(\"\\=[abciow12]/.*\\|/dev/null\\)$'\nfunction! s:cfile() abort\n  let temp_state = s:TempState()\n  let name = substitute(get(get(temp_state, 'args', []), 0, ''), '\\%(^\\|-\\)\\(\\l\\)', '\\u\\1', 'g')\n  if exists('*s:' . name . 'Cfile')\n    let cfile = s:{name}Cfile(temp_state)\n    if !empty(cfile)\n      return type(cfile) == type('') ? [cfile] : cfile\n    endif\n  endif\n  if empty(FugitiveGitDir())\n    return []\n  endif\n  try\n    let myhash = s:DirRev(@%)[1]\n    if len(myhash)\n      try\n        let myhash = fugitive#RevParse(myhash)\n      catch /^fugitive:/\n        let myhash = ''\n      endtry\n    endif\n    if empty(myhash) && get(temp_state, 'filetype', '') ==# 'git'\n      let lnum = line('.')\n      while lnum > 0\n        if getline(lnum) =~# '^\\%(commit\\|tag\\) \\w'\n          let myhash = matchstr(getline(lnum),'^\\w\\+ \\zs\\S\\+')\n          break\n        endif\n        let lnum -= 1\n      endwhile\n    endif\n\n    let showtree = (getline(1) =~# '^tree ' && getline(2) == \"\")\n\n    let treebase = substitute(s:DirCommitFile(@%)[1], '^\\d$', ':&', '') . ':' .\n          \\ s:Relative('') . (s:Relative('') =~# '^$\\|/$' ? '' : '/')\n\n    if getline('.') =~# '^\\d\\{6\\} \\l\\{3,8\\} \\x\\{40,\\}\\t'\n      return [treebase . s:sub(matchstr(getline('.'),'\\t\\zs.*'),'/$','')]\n    elseif showtree\n      return [treebase . s:sub(getline('.'),'/$','')]\n\n    else\n\n      let dcmds = []\n\n      \" Index\n      if getline('.') =~# '^\\d\\{6\\} \\x\\{40,\\} \\d\\t'\n        let ref = matchstr(getline('.'),'\\x\\{40,\\}')\n        let file = ':'.s:sub(matchstr(getline('.'),'\\d\\t.*'),'\\t',':')\n        return [file]\n      endif\n\n      if getline('.') =~# '^ref: '\n        let ref = strpart(getline('.'),5)\n\n      elseif getline('.') =~# '^\\%([|/\\\\_ ]*\\*[|/\\\\_ ]*\\)\\=commit \\x\\{40,\\}\\>'\n        let ref = matchstr(getline('.'),'\\x\\{40,\\}')\n        return [ref]\n\n      elseif getline('.') =~# '^parent \\x\\{40,\\}\\>'\n        let ref = matchstr(getline('.'),'\\x\\{40,\\}')\n        let line = line('.')\n        let parent = 0\n        while getline(line) =~# '^parent '\n          let parent += 1\n          let line -= 1\n        endwhile\n        return [ref]\n\n      elseif getline('.') =~# '^tree \\x\\{40,\\}$'\n        let ref = matchstr(getline('.'),'\\x\\{40,\\}')\n        if len(myhash) && fugitive#RevParse(myhash.':') ==# ref\n          let ref = myhash.':'\n        endif\n        return [ref]\n\n      elseif getline('.') =~# '^object \\x\\{40,\\}$' && getline(line('.')+1) =~ '^type \\%(commit\\|tree\\|blob\\)$'\n        let ref = matchstr(getline('.'),'\\x\\{40,\\}')\n        let type = matchstr(getline(line('.')+1),'type \\zs.*')\n\n      elseif getline('.') =~# '^\\l\\{3,8\\} '.myhash.'$'\n        let ref = s:DirRev(@%)[1]\n\n      elseif getline('.') =~# '^\\l\\{3,8\\} \\x\\{40,\\}\\>'\n        let ref = matchstr(getline('.'),'\\x\\{40,\\}')\n        echoerr \"warning: unknown context \".matchstr(getline('.'),'^\\l*')\n\n      elseif getline('.') =~# '^[A-Z]\\d*\\t\\S' && len(myhash)\n        let files = split(getline('.'), \"\\t\")[1:-1]\n        let ref = 'b/' . files[-1]\n        if getline('.') =~# '^D'\n          let ref = 'a/' . files[0]\n        elseif getline('.') !~# '^A'\n          let dcmds = ['', 'Gdiffsplit! >' . myhash . '^:' . fnameescape(files[0])]\n        endif\n\n      elseif getline('.') =~# '^[+-]'\n        let [header_lnum, old_lnum, new_lnum] = s:HunkPosition(line('.'))\n        if new_lnum > 0\n          let ref = s:ParseDiffHeader(getline(search(s:diff_header_pattern, 'bnW')))[1]\n          let dcmds = [new_lnum, 'normal!zv']\n        elseif old_lnum > 0\n          let ref = s:ParseDiffHeader(getline(search(s:diff_header_pattern, 'bnW')))[0]\n          let dcmds = [old_lnum, 'normal!zv']\n        else\n          let ref = fugitive#Unquote(matchstr(getline('.'), '\\C[+-]\\{3\\} \\zs\"\\=[abciow12]/.*'))\n        endif\n\n      elseif getline('.') =~# '^rename from '\n        let ref = 'a/'.getline('.')[12:]\n      elseif getline('.') =~# '^rename to '\n        let ref = 'b/'.getline('.')[10:]\n\n      elseif getline('.') =~# '^@@ -\\d\\+\\%(,\\d\\+\\)\\= +\\d\\+'\n        let diff = getline(search(s:diff_header_pattern, 'bcnW'))\n        let offset = matchstr(getline('.'), '+\\zs\\d\\+')\n\n        let [dref, ref] = s:ParseDiffHeader(diff)\n        let dcmd = 'Gdiffsplit! +'.offset\n\n      elseif getline('.') =~# s:diff_header_pattern\n        let [dref, ref] = s:ParseDiffHeader(getline('.'))\n        let dcmd = 'Gdiffsplit!'\n\n      elseif getline('.') =~# '^index ' && getline(line('.')-1) =~# s:diff_header_pattern\n        let [dref, ref] = s:ParseDiffHeader(getline(line('.') - '.'))\n        let dcmd = 'Gdiffsplit!'\n\n      elseif line('$') == 1 && getline('.') =~ '^\\x\\{40,\\}$'\n        let ref = getline('.')\n\n      elseif expand('<cword>') =~# '^\\x\\{7,\\}\\>'\n        return [expand('<cword>')]\n\n      else\n        let ref = ''\n      endif\n\n      let prefixes = {\n            \\ '1': '',\n            \\ '2': '',\n            \\ 'b': ':0:',\n            \\ 'i': ':0:',\n            \\ 'o': '',\n            \\ 'w': ''}\n\n      if len(myhash)\n        let prefixes.a = myhash.'^:'\n        let prefixes.b = myhash.':'\n      endif\n      let ref = substitute(ref, '^\\(\\w\\)/', '\\=get(prefixes, submatch(1), \"@:\")', '')\n      if exists('dref')\n        let dref = substitute(dref, '^\\(\\w\\)/', '\\=get(prefixes, submatch(1), \"@:\")', '')\n      endif\n\n      if ref ==# '/dev/null'\n        \" Empty blob\n        let ref = 'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391'\n      endif\n\n      if exists('dref')\n        return [ref, dcmd . ' >' . s:fnameescape(dref)] + dcmds\n      elseif ref != \"\"\n        return [ref] + dcmds\n      endif\n\n    endif\n    return []\n  endtry\nendfunction\n\nfunction! s:GF(mode) abort\n  try\n    let results = &filetype ==# 'fugitive' ? s:CfilePorcelain() : &filetype ==# 'gitcommit' ? s:StatusCfile() : s:cfile()\n  catch /^fugitive:/\n    return 'echoerr ' . string(v:exception)\n  endtry\n  if len(results) > 1\n    let cmd = 'G' . a:mode .\n          \\ (empty(results[1]) ? '' : ' +' . s:PlusEscape(results[1])) . ' ' .\n          \\ fnameescape(results[0])\n    let tail = join(map(results[2:-1], '\"|\" . v:val'), '')\n    if a:mode ==# 'pedit' && len(tail)\n      return cmd . '|wincmd P|exe ' . string(tail[1:-1]) . '|wincmd p'\n    else\n      return cmd . tail\n    endif\n  elseif len(results) && len(results[0])\n    return 'G' . a:mode . ' ' . s:fnameescape(results[0])\n  else\n    return ''\n  endif\nendfunction\n\nfunction! fugitive#Cfile() abort\n  let pre = ''\n  let results = s:cfile()\n  if empty(results)\n    if !empty(s:TempState())\n      let cfile = s:TempDotMap()\n      if !empty(cfile)\n        return fnameescape(s:Generate(cfile))\n      endif\n    endif\n    let cfile = expand('<cfile>')\n    if &includeexpr =~# '\\<v:fname\\>'\n      sandbox let cfile = eval(substitute(&includeexpr, '\\C\\<v:fname\\>', '\\=string(cfile)', 'g'))\n    endif\n    return cfile\n  elseif len(results) > 1\n    let pre = '+' . join(map(results[1:-1], 'escape(v:val, \" \")'), '\\|') . ' '\n  endif\n  return pre . fnameescape(s:Generate(results[0]))\nendfunction\n\n\" Section: Statusline\n\nfunction! fugitive#Statusline(...) abort\n  let dir = s:Dir(bufnr(''))\n  if empty(dir)\n    return ''\n  endif\n  let status = ''\n  let commit = s:DirCommitFile(@%)[1]\n  if len(commit)\n    let status .= ':' . commit[0:6]\n  endif\n  let status .= '('.fugitive#Head(7, dir).')'\n  return '[Git'.status.']'\nendfunction\n\nfunction! fugitive#statusline(...) abort\n  return fugitive#Statusline()\nendfunction\n\n\" Section: Folding\n\nfunction! fugitive#Foldtext() abort\n  if &foldmethod !=# 'syntax'\n    return foldtext()\n  endif\n\n  let line_foldstart = getline(v:foldstart)\n  if line_foldstart =~# '^diff '\n    let [add, remove] = [-1, -1]\n    let filename = ''\n    for lnum in range(v:foldstart, v:foldend)\n      let line = getline(lnum)\n      if filename ==# '' && line =~# '^[+-]\\{3\\} \"\\=[abciow12]/'\n        let filename = fugitive#Unquote(line[4:-1])[2:-1]\n      endif\n      if line =~# '^+'\n        let add += 1\n      elseif line =~# '^-'\n        let remove += 1\n      elseif line =~# '^Binary '\n        let binary = 1\n      endif\n    endfor\n    if filename ==# ''\n      let filename = fugitive#Unquote(matchstr(line_foldstart, '^diff .\\{-\\} \\zs\"\\=[abciow12]/\\zs.*\\ze \"\\=[abciow12]/'))[2:-1]\n    endif\n    if filename ==# ''\n      let filename = line_foldstart[5:-1]\n    endif\n    if exists('binary')\n      return 'Binary: '.filename\n    else\n      return '+-' . v:folddashes . ' ' . (add<10&&remove<100?' ':'') . add . '+ ' . (remove<10&&add<100?' ':'') . remove . '- ' . filename\n    endif\n  elseif line_foldstart =~# '^@@\\+ .* @@'\n    return '+-' . v:folddashes . ' ' . line_foldstart\n  elseif &filetype ==# 'fugitive' && line_foldstart =~# '^[A-Z][a-z].* (\\d\\+)$'\n    let c = +matchstr(line_foldstart, '(\\zs\\d\\+\\ze)$')\n    return '+-' . v:folddashes . printf('%3d item', c) . (c == 1 ? ':  ' : 's: ') . matchstr(line_foldstart, '.*\\ze (\\d\\+)$')\n  elseif &filetype ==# 'gitcommit' && line_foldstart =~# '^# .*:$'\n    let lines = getline(v:foldstart, v:foldend)\n    call filter(lines, 'v:val =~# \"^#\\t\"')\n    call map(lines, \"s:sub(v:val, '^#\\t%(modified: +|renamed: +)=', '')\")\n    call map(lines, \"s:sub(v:val, '^([[:alpha:] ]+): +(.*)', '\\\\2 (\\\\1)')\")\n    return line_foldstart.' '.join(lines, ', ')\n  endif\n  return foldtext()\nendfunction\n\nfunction! fugitive#foldtext() abort\n  return fugitive#Foldtext()\nendfunction\n\n\" Section: End\n"
  },
  {
    "path": "doc/fugitive.txt",
    "content": "*fugitive.txt*  A Git wrapper so awesome, it should be illegal\n\nAuthor:  Tim Pope <http://tpo.pe/>\nLicense: Same terms as Vim itself (see |license|)\n\nThis plugin is only available if 'compatible' is not set.\n\nINTRODUCTION                                    *fugitive*\n\nWhenever you edit a file from a Git repository, a set of commands is defined\nthat serve as a gateway to Git.\n\nCOMMANDS                                        *fugitive-commands*\n\nThese commands are local to the buffers in which they work (generally, buffers\nthat are part of Git repositories).\n\n                                                *fugitive-:G*\n:G [args]               Same as :Git, but two characters shorter.\n\n                                                *fugitive-summary*\n:Git                    With no arguments, bring up a summary window vaguely\n                        akin to git-status.  If a summary window is already\n                        open for the current repository, it is focused\n                        instead.  Press g?  or see |fugitive-maps| for usage.\n\n                                                *:Git*\n:Git {args}             Run an arbitrary git command and display any output.\n                        On UNIX this uses a pty and on other platforms it uses\n                        a pipe, which will cause some behavior differences\n                        such as the absence of progress bars.  Any file the\n                        command edits (for example, a commit message) will be\n                        loaded into a split window.  Closing that window will\n                        resume running the command.  A few Git subcommands\n                        have different behavior; these are documented below.\n\n                                                *:Git!*\n:Git! {args}            Run an arbitrary git command in the background and\n                        stream the output to the preview window.  Requires a\n                        Vim with |setbufline()|.  Press CTRL-D during an\n                        interactive :Git invocation to switch to this mode\n                        retroactively.\n\n                                                *:Git_--paginate* *:Git_-p*\n:Git --paginate {args}  Run an arbitrary git command, capture output to a temp\n:Git -p {args}          file, and |:split| that temp file.  Pass ++curwin as\n                        the first argument to |:edit| the temp file instead.\n                        A temp file is always used for commands like diff and\n                        log that typically uses a pager, and for any command\n                        that has the pager.<cmd> Git configuration option set.\n\n:{range}Git! --paginate {args}\n:{range}Git! -p {args}  Run an arbitrary git command, and insert the output\n                        after {range} in the current buffer.\n\n                                                *:Git_blame*\n:Git blame [flags]      Run git-blame [flags] on the current file and open the\n                        results in a scroll-bound vertical split.  The\n                        following maps, which work on the cursor line commit\n                        where sensible, are provided:\n\n                        g?    show this help\n                        A     resize to end of author column\n                        C     resize to end of commit column\n                        D     resize to end of date/time column\n                        gq    close blame, then |:Gedit| to return to work\n                              tree version\n                        <CR>  close blame, and jump to patch that added line\n                              (or directly to blob for boundary commit)\n                        o     jump to patch or blob in horizontal split\n                        O     jump to patch or blob in new tab\n                        p     jump to patch or blob in preview window\n                        -     reblame at commit\n\n                        The maps |fugitive_P| and |fugitive_~| are also\n                        supported to reblame on a parent commit, but this is\n                        inherently fragile, as the line being blamed will no\n                        longer exist.  The preferred alternative is to use\n                        <CR> to open up the commit, select the corresponding\n                        `-` line that you care about, and press <CR> twice\n                        more to reblame at that line.  Viewing the commit also\n                        gives you additional context as to why the line\n                        changed.\n\n                                                *g:fugitive_dynamic_colors*\n                        In the GUI or a 256 color terminal, commit hashes will\n                        be highlighted in different colors. To disable this:\n>\n                        let g:fugitive_dynamic_colors = 0\n<\n:[range]Git blame [...] If a range is given, just that part of the file will\n:Git blame [...] {file} be blamed, and a horizontal split without\n                        scrollbinding is used.  You can also give an arbitrary\n                        filename.\n\n                                                *:Git_difftool*\n:Git[!] difftool [args] Invoke `git diff [args]` and load the changes into the\n                        quickfix list.  Each changed hunk gets a separate\n                        quickfix entry unless you pass an option like\n                        --name-only or --name-status.  Jumps to the first\n                        change unless [!] is given.\n\n:Git difftool -y [args] Invoke `git diff [args]`, open each changed file in a\n                        new tab, and invoke |:Gdiffsplit!| against the\n                        appropriate commit.\n\n                                                *:Git_mergetool*\n:Git mergetool [args]   Like |:Git_difftool|, but target merge conflicts.\n\nWrappers for Vim built-ins ~\n\nThese all directly map onto a built-in Vim command, and generally have names\nthat prepend \"G\" to the command they are wrapping.  For example, :Ggrep is G\nplus |:grep|.\n\n                                                *:Ggrep* *:Git_grep*\n:Ggrep[!] [args]        An approximation of |:grep|[!] with git-grep as\n:Git[!] grep -O [args]  'grepprg'.\n\n:Ggrep[!] --quiet [args]\n:Ggrep[!] -q [args]     Like |:Ggrep|, but instead of displaying output, open\n                        the quickfix list.\n\n                                                *:Glgrep*\n:Glgrep[!] [args]       :Ggrep but for |:lgrep|.\n:0Git[!] grep -O [args]\n\n                                                 *:Gclog*\n:Gclog[!] [args]        Use git-log [args] to load the commit history into the\n                        |quickfix| list.  Jumps to the first commit unless [!]\n                        is given.  This command wraps |:cfile|.\n\n                        The quickfix list can be awkward for many use cases\n                        and exhibits extremely poor performance with larger\n                        data sets.  Consider using |:Git| log --oneline\n                        instead.\n\n:{range}Gclog[!] [args] Use git-log -L to load previous revisions of the given\n                        range of the current file into the |quickfix| list.\n                        The cursor is positioned on the first line of the\n                        first diff hunk for each commit.  Use :0Gclog to\n                        target the entire file.\n\n                                                *:Gllog*\n:Gllog [args]           Like |:Gclog|, but use the location list instead of the\n                        |quickfix| list.\n\n                                                *:Gcd*\n:Gcd [directory]        |:cd| relative to the repository.\n\n                                                *:Glcd*\n:Glcd [directory]       |:lcd| relative to the repository.\n\n                                                *:Gedit* *fugitive-:Ge*\n:Gedit [object]         |:edit| a |fugitive-object|.\n\n                                                *:Gsplit*\n:Gsplit [object]        |:split| a |fugitive-object|.\n\n                                                *:Gvsplit*\n:Gvsplit [object]       |:vsplit| a |fugitive-object|.\n\n                                                *:Gtabedit*\n:Gtabedit [object]      |:tabedit| a |fugitive-object|.\n\n                                                *:Gpedit*\n:Gpedit [object]        |:pedit| a |fugitive-object|.\n\n                                                *:Gdrop*\n:Gdrop [object]         |:drop| a |fugitive-object|.\n\n                                                *:Gread* *fugitive-:Gr*\n:Gread [object]         Empty the buffer and |:read| a |fugitive-object|.\n                        When the argument is omitted, this is similar to\n                        git-checkout on a work tree file or git-add on a stage\n                        file, but without writing anything to disk.\n\n:{range}Gread [object]  |:read| in a |fugitive-object| after {range}.\n\n                                                *:Gwrite* *fugitive-:Gw*\n:Gwrite                 Write to the current file's path and stage the results.\n                        When run in a work tree file, it is effectively git\n                        add.  Elsewhere, it is effectively git-checkout.  A\n                        great deal of effort is expended to behave sensibly\n                        when the work tree or index version of the file is\n                        open in another buffer.\n\n:Gwrite {path}          You can give |:Gwrite| an explicit path of where in\n                        the work tree to write.  You can also give a path like\n                        :0:foo.txt or :0:% to write to just that stage in\n                        the index.\n\n                                                *:Gwq*\n:Gwq [path]             Like |:Gwrite| followed by |:quit| if the write\n                        succeeded.\n\n:Gwq! [path]            Like |:Gwrite|! followed by |:quit|! if the write\n                        succeeded.\n\n                                                *:Gdiffsplit*\n:Gdiffsplit [object]    Perform a |vimdiff| against the given file, or if a\n                        commit is given, the current file in that commit.\n                        With no argument, the version in the index or work\n                        tree is used, and the work tree version is always\n                        placed to the right or bottom, depending on available\n                        width.  Use Vim's |do| and |dp| to stage and unstage\n                        changes.\n\n                                                *:Gdiffsplit!*\n:Gdiffsplit!            Diff against any and all direct ancestors, retaining\n                        focus on the current window.  During a merge conflict,\n                        this is a three-way diff against the \"ours\" and\n                        \"theirs\" ancestors.  Additional d2o and d3o maps are\n                        provided to obtain the hunk from the \"ours\" or\n                        \"theirs\" ancestor, respectively.\n\n:Gdiffsplit! {object}   Like |:Gdiffsplit|, but retain focus on the current\n                        window.\n\n                                                *:Gvdiffsplit*\n:Gvdiffsplit [object]   Like |:Gdiffsplit|, but always split vertically.\n\n                                                *:Ghdiffsplit*\n:Gdiffsplit ++novertical [object]\n:Ghdiffsplit [object]   Like |:Gdiffsplit|, but with \"vertical\" removed from\n                        'diffopt'.  The split will still be vertical if\n                        combined with |:vertical|.\n\nOther commands ~\n\nThese do not directly correspond to any built-in Vim command, and have a\ncapital letter after the \"G\" to convey this. For example, the file move\noperation has nothing to do with the |:move| built-in, so it is named :GMove,\nnot :Gmove.\n\n                                                *:GMove*\n:GMove {destination}    Wrapper around git-mv that renames the buffer\n                        afterward.  Add a ! to pass -f.\n\n                                                *:GRename*\n:GRename {destination}  Like |:GMove| but operates relative to the parent\n                        directory of the current file.\n\n                                                *:GDelete*\n:GDelete                Wrapper around git-rm that deletes the buffer\n                        afterward.  When invoked in an index file, --cached is\n                        passed.  Add a ! to pass -f and forcefully discard the\n                        buffer.\n\n                                                *:GRemove* *:GUnlink*\n:GRemove                Like |:GDelete|, but keep the (now empty) buffer around.\n:GUnlink\n\n                                                *:GBrowse*\n:GBrowse                Open the current file, blob, tree, commit, or tag\n                        in your browser at the upstream hosting provider.\n                        Upstream providers can be added by installing an\n                        appropriate Vim plugin.  For example, GitHub can be\n                        supported by installing rhubarb.vim, available at\n                        <https://github.com/tpope/vim-rhubarb>.\n\n:GBrowse {object}       Like :GBrowse, but for a given |fugitive-object|.\n\n:{range}GBrowse [args]  Appends an anchor to the URL that emphasizes the\n                        selected lines. This also forces the URL to include a\n                        commit rather than a branch name so it remains valid\n                        if the file changes.  You can give a range of \"0\" to\n                        force this behavior without including an anchor.\n\n:GBrowse [...]@{remote} Force using the given remote rather than the remote\n                        for the current branch.  The remote is used to\n                        determine which upstream repository to link to.\n\n:GBrowse {url}          Open an arbitrary URL in your browser.\n\n:[range]GBrowse! [args] Like :GBrowse, but put the URL on the clipboard rather\n                        than opening it.\n\nMAPS                                            *fugitive-maps*\n\nThese maps are available in both the |fugitive-summary| buffer and Fugitive\nobject buffers, although not all maps make sense in all buffers.  Mappings\nthat operate on the file or hunk under the cursor are generally available in\nvisual mode to operate on multiple files or partial hunks.\n\n                                                *fugitive-staging-maps*\nStaging/unstaging maps ~\n\n                                                *fugitive_s*\ns                       Stage (add) the file or hunk under the cursor.\n\n                                                *fugitive_u*\nu                       Unstage (reset) the file or hunk under the cursor.\n\n                                                *fugitive_-*\n-                       Stage or unstage the file or hunk under the cursor.\n\n                                                *fugitive_U*\nU                       Unstage everything.\n\n                                                *fugitive_X*\nX                       Discard the change under the cursor.  This uses\n                        `checkout` or `clean` under the hood.  A command is\n                        echoed that shows how to undo the change.  Consult\n                        `:messages` to see it again.  During a merge conflict,\n                        use 2X to call `checkout --ours` or 3X to call\n                        `checkout --theirs` .\n\n                                                *fugitive_=*\n=                       Toggle an inline diff of the file under the cursor.\n\n                                                *fugitive_>*\n>                       Insert an inline diff of the file under the cursor.\n\n                                                *fugitive_<*\n<                       Remove the inline diff of the file under the cursor.\n\n                                                *fugitive_gI*\ngI                      Open .git/info/exclude in a split and add the file\n                        under the cursor.  Use a count to open .gitignore.\n\n                                                *fugitive_I*\nI                       Invoke |:Git| add --patch or reset --patch on the file\nP                       under the cursor. On untracked files, this instead\n                        calls |:Git| add --intent-to-add.\n\n                                                *fugitive_d*\nDiff maps ~\n                                                *fugitive_dp*\ndp                      Invoke |:Git| diff on the file under the cursor.\n                        Deprecated in favor of inline diffs.\n\n                                                *fugitive_dd*\ndd                      Perform a |:Gdiffsplit| on the file under the cursor.\n\n                                                *fugitive_dv*\ndv                      Perform a |:Gvdiffsplit| on the file under the cursor.\n\n                                                *fugitive_ds* *fugitive_dh*\nds                      Perform a |:Ghdiffsplit| on the file under the cursor.\ndh\n\n                                                *fugitive_dq*\ndq                      Close all but the currently focused diff buffer, and\n                        invoke |:diffoff|!.\n\n                                                *fugitive_d?*\nd?                      Show this help.\n\n                                                *fugitive-navigation-maps*\nNavigation maps ~\n\n                                                *fugitive_<CR>*\n<CR>                    Open the file or |fugitive-object| under the cursor.\n                        In a blob, this and similar maps jump to the patch\n                        from the diff where this was added, or where it was\n                        removed if a count was given.  If the line is still in\n                        the work tree version, passing a count takes you to\n                        it.\n\n                                                *fugitive_o*\no                       Open the file or |fugitive-object| under the cursor in\n                        a new split.\n\n                                                *fugitive_gO*\ngO                      Open the file or |fugitive-object| under the cursor in\n                        a new vertical split.\n\n                                                *fugitive_O*\nO                       Open the file or |fugitive-object| under the cursor in\n                        a new tab.\n\n                                                *fugitive_p*\np                       Open the file or |fugitive-object| under the cursor in\n                        a preview window.  In the status buffer, 1p is\n                        required to bypass the legacy usage instructions.\n\n                                                *fugitive_~*\n~                       Open the current file in the [count]th first ancestor.\n\n                                                *fugitive_P*\nP                       Open the current file in the [count]th parent.\n                        Experimental:  In the \"Unpushed\" section of the status\n                        buffer, this will populate the command line with a\n                        \":Git push\" command for the commit under the cursor.\n\n                                                *fugitive_C*\nC                       Open the commit containing the current file.\n\n                                                *fugitive_CTRL-P* *fugitive_(*\n(                       Jump to the previous file, hunk, or revision.\n\n                                                *fugitive_CTRL-N* *fugitive_)*\n)                       Jump to the next file, hunk, or revision.\n\n                                                *fugitive_[c*\n[c                      Jump to previous hunk, expanding inline diffs\n                        automatically.  (This shadows the Vim built-in |[c|\n                        that provides a similar operation in |diff| mode.)\n\n                                                *fugitive_]c*\n]c                      Jump to next hunk, expanding inline diffs\n                        automatically.  (This shadows the Vim built-in |]c|\n                        that provides a similar operation in |diff| mode.)\n\n                                                *fugitive_[/* *fugitive_[m*\n[/                      Jump to previous file, collapsing inline diffs\n[m                      automatically.  (Mnemonic: \"/\" appears in filenames,\n                        \"m\" appears in \"filenames\".)\n\n                                                *fugitive_]/* *fugitive_]m*\n]/                      Jump to next file, collapsing inline diffs\n]m                      automatically.  (Mnemonic: \"/\" appears in filenames,\n                        \"m\" appears in \"filenames\".)\n\n                                                *fugitive_i*\ni                       Jump to the next file or hunk, expanding inline diffs\n                        automatically.\n\n                                                *fugitive_[[*\n[[                      Jump [count] sections backward.\n\n                                                *fugitive_]]*\n]]                      Jump [count] sections forward.\n\n                                                *fugitive_[]*\n[]                      Jump [count] section ends backward.\n\n                                                *fugitive_][*\n][                      Jump [count] section ends forward.\n\n                                                *fugitive_star*\n*                       On the first column of a + or - diff line, search for\n                        the corresponding - or + line.  Otherwise, defer to\n                        built-in |star|.\n\n                                                *fugitive_#*\n#                       Same as \"*\", but search backward.\n\n                                                *fugitive_gu*\ngu                      Jump to file [count] in the \"Untracked\" or \"Unstaged\"\n                        section.\n\n                                                *fugitive_gU*\ngU                      Jump to file [count] in the \"Unstaged\" section.\n\n                                                *fugitive_gs*\ngs                      Jump to file [count] in the \"Staged\" section.\n\n                                                *fugitive_gp*\ngp                      Jump to file [count] in the \"Unpushed\" section.\n\n                                                *fugitive_gP*\ngP                      Jump to file [count] in the \"Unpulled\" section.\n\n                                                *fugitive_gr*\ngr                      Jump to file [count] in the \"Rebasing\" section.\n\n                                                *fugitive_gi*\ngi                      Open .git/info/exclude in a split.  Use a count to\n                        open .gitignore.\n\n                                                *fugitive_c*\nCommit maps ~\n\ncc                      Create a commit.\n\ncvc                     Create a commit with -v.\n\nca                      Amend the last commit and edit the message.\n\ncva                     Amend the last commit with -v.\n\nce                      Amend the last commit without editing the message.\n\ncw                      Reword the last commit.\n\ncW                      Create an `amend!` commit that rewords the commit\n                        under the cursor.\n\ncf                      Create a `fixup!` commit for the commit under the\n                        cursor.\n\ncF                      Create a `fixup!` commit for the commit under the\n                        cursor and immediately rebase it.\n\ncs                      Create a `squash!` commit for the commit under the\n                        cursor.\n\ncS                      Create a `squash!` commit for the commit under the\n                        cursor and immediately rebase it.\n\ncn                      Create a `squash!` commit for the commit under the\n(formerly cA)           cursor and edit the message.\n\nc<Space>                Populate command line with \":Git commit \".\n\n                                                *fugitive_cr*\ncrc                     Revert the commit under the cursor.\n\ncrn                     Revert the commit under the cursor in the index and\n                        work tree, but do not actually commit the changes.\n\ncr<Space>               Populate command line with \":Git revert \".\n\n                                                *fugitive_cm*\ncm<Space>               Populate command line with \":Git merge \".\n\nc?                      Show this help.\n\n                                                *fugitive_cb*\n                                                *fugitive_co*\nCheckout/branch maps ~\n\ncoo                     Check out the commit under the cursor.\n\ncb<Space>               Populate command line with \":Git branch \".\n\nco<Space>               Populate command line with \":Git checkout \".\n\ncb?                     Show this help.\nco?\n\n                                                *fugitive_cz*\nStash maps ~\n\nczz                     Push stash.  Pass a [count] of 1 to add\n                        `--include-untracked` or 2 to add `--all`.\n\nczw                     Push stash of the work-tree.  Like `czz` with\n                        `--keep-index`.\n\nczs                     Push stash of the stage.  Does not accept a count.\n\nczA                     Apply topmost stash, or stash@{count}.\n\ncza                     Apply topmost stash, or stash@{count}, preserving the\n                        index.\n\nczP                     Pop topmost stash, or stash@{count}.\n\nczp                     Pop topmost stash, or stash@{count}, preserving the\n                        index.\n\ncz<Space>               Populate command line with \":Git stash \".\n\ncz?                     Show this help.\n\n                                                *fugitive_r*\nRebase maps ~\n\nri                      Perform an interactive rebase.  Uses ancestor of\nu                       commit under cursor as upstream if available.\n\nrf                      Perform an autosquash rebase without editing the todo\n                        list.  Uses ancestor of commit under cursor as\n                        upstream if available.\n\nru                      Perform an interactive rebase against @{upstream}.\n\nrp                      Perform an interactive rebase against @{push}.\n\nrr                      Continue the current rebase.\n\nrs                      Skip the current commit and continue the current\n                        rebase.\n\nra                      Abort the current rebase.\n\nre                      Edit the current rebase todo list.\n\nrw                      Perform an interactive rebase with the commit under\n                        the cursor set to `reword`.\n\nrm                      Perform an interactive rebase with the commit under\n                        the cursor set to `edit`.\n\nrd                      Perform an interactive rebase with the commit under\n                        the cursor set to `drop`.\n\nr<Space>                Populate command line with \":Git rebase \".\n\nr?                      Show this help.\n\n                                                *fugitive-misc-maps*\nMiscellaneous maps ~\n\n                                                *fugitive_gq* *fugitive_q*\ngq                      Close the status buffer.\n\n                                                *fugitive_.*\n.                       Start a |:| command line with the file under the\n                        cursor prepopulated.\n\n                                                *fugitive_g?*\ng?                      Show help for |fugitive-maps|.\n\n                                                *fugitive-global-maps*\nGlobal maps ~\n\n                                                *fugitive_c_CTRL-R_CTRL-G*\n<C-R><C-G>              On the command line, recall the path to the current\n                        |fugitive-object| (that is, a representation of the\n                        object recognized by |:Gedit|).\n\n                                                *fugitive_y_CTRL-G*\n[\"x]y<C-G>              Yank the path to the current |fugitive-object|.\n\n                                                *g:fugitive_no_maps*\nGlobal maps can be disabled with the g:fugitive_no_maps option.\n>\n        let g:fugitive_no_maps = 1\n<\nSPECIFYING OBJECTS                      *fugitive-object* *fugitive-revision*\n\nFugitive objects are either work tree files or Git revisions as defined in the\n\"SPECIFYING REVISIONS\" section in the git-rev-parse man page, with expansions\ninspired by |cmdline-special| layered on top.  For commands that accept an\noptional object, the default is the file in the index for work tree files and\nthe work tree file for everything else.  Example objects follow.\n\nObject          Meaning ~\n@               The commit referenced by @ aka HEAD\nmaster          The commit referenced by master\nmaster^         The parent of the commit referenced by master\nmaster...other  The merge base of master and other\nmaster:         The tree referenced by master\n./master        The file named master in the working directory\n:(top)master    The file named master in the work tree\nMakefile        The file named Makefile in the work tree\n@^:Makefile     The file named Makefile in the parent of HEAD\n:Makefile       The file named Makefile in the index (writable)\n@~2:%           The current file in the grandparent of HEAD\n:%              The current file in the index\n:1:%            The current file's common ancestor during a conflict\n:2:#            The alternate file in the target branch during a conflict\n:3:#5           The file from buffer #5 in the merged branch during a conflict\n!               The commit owning the current file\n!:Makefile      The file named Makefile in the commit owning the current file\n!3^2            The second parent of the commit owning buffer #3\n.git/config     The repo config file\n:               The |fugitive-summary| buffer\n-               A temp file containing the last |:Git| invocation's output\n<cfile>         The file or commit under the cursor\n\nSTATUSLINE                                      *fugitive-statusline*\n\n                                *FugitiveStatusline()* *fugitive#statusline()*\nAdd %{FugitiveStatusline()} to your statusline to get an indicator including\nthe current branch and the currently edited file's commit.  If you don't have\na statusline, this one matches the default when 'ruler' is set:\n>\n        set statusline=%<%f\\ %h%m%r%{FugitiveStatusline()}%=%-14.(%l,%c%V%)\\ %P\n<\nAUTOCOMMANDS                                    *fugitive-autocommands*\n\nA handful of |User| |autocommands| are provided to allow extending and\noverriding Fugitive behaviors.  Example usage:\n>\n        autocmd User FugitiveBlob,FugitiveStageBlob call s:BlobOverrides()\n<\n                                                *User_FugitiveTag*\nFugitiveTag             After loading a tag object.\n\n                                                *User_FugitiveCommit*\nFugitiveCommit          After loading a commit object.\n\n                                                *User_FugitiveTree*\nFugitiveTree            After loading a tree (directory) object.\n\n                                                *User_FugitiveBlob*\nFugitiveBlob            After loading a committed blob (file) object.\n\n                                                *User_FugitiveObject*\nFugitiveObject          After loading any of the 4 above buffer types.\n\n                                                *User_FugitiveStageBlob*\nFugitiveStageBlob       After loading a staged blob (file) object.  These\n                        buffers are 'modifiable' and oftentimes don't want the\n                        same behavior as the other buffer types.\n\n                                                *User_FugitiveIndex*\nFugitiveIndex           After loading the |fugitive-summary| buffer.\n\n                                                *User_FugitivePager*\nFugitivePager           After loading a temp file created by a command like\n                        :Git --paginate or :Git blame.\n\n                                                *User_FugitiveEditor*\nFugitiveEditor          After a :Git command (e.g., :Git commit) edits a file\n                        (e.g., the commit message).\n\n                                                *User_FugitiveChanged*\nFugitiveChanged         After any event which can potentially change the\n                        repository, for example, any invocation of |:Git|.\n                        Originally intended for expiring caches, but can have\n                        other uses.\n\nAPI                                             *fugitive-api*\n\nOfficially supported functions are documented inline in plugin/fugitive.vim.\n\nDEPRECATIONS                                    *fugitive-deprecated*\n\nThe following commands are deprecated in favor of replacements that adhere to\na new naming scheme.  Remember that |:Git| can be shortened to |:G|, so\nreplacements using it are just one space character longer than the legacy\nversion.\n\n*:Gremove*      Superseded by |:GRemove|.\n*:Gdelete*      Superseded by |:GDelete|.\n*:Gmove*        Superseded by |:GMove|.\n*:Grename*      Superseded by |:GRename|.\n*:Gbrowse*      Superseded by |:GBrowse|.\n*:Gdiff*        Superseded by |:Gdiffsplit|\n*:Gsdiff*       Superseded by |:Ghdiffsplit|\n*:Gvdiff*       Superseded by |:Gvdiffsplit| or |:vert| |:Gdiffsplit|.\n*:Gblame*       Superseded by |:Git_blame|.\n*:Gcommit*      Superseded by |:Git| commit.\n*:Gmerge*       Superseded by |:Git| merge and |:Git_mergetool|.\n*:Gpull*        Superseded by |:Git| pull.\n*:Grebase*      Superseded by |:Git| rebase.\n*:Grevert*      Superseded by |:Git| revert.\n*:Gpush*        Superseded by |:Git| push.\n*:Gfetch*       Superseded by |:Git| fetch.\n*:Glog*         Superseded by |:Gclog|.\n*:Gstatus*      Superseded by |:Git| (with no arguments).\n*:Gsplit!*      Superseded by |:Git_--paginate|.\n*:Gvsplit!*     Superseded by :vert Git --paginate.\n*:Gtabsplit!*   Superseded by :tab Git --paginate.\n*:Gpedit!*      Superseded by :Git! --paginate.\n\n                                                *User_Fugitive*\nFugitive used to support `:autocmd User Fugitive` to run an autocommand after\nloading any buffer belonging to a Git repository, but this has been phased\nout.  Instead, one can leverage regular autocommand events like |BufNewFile|\nand |BufReadPost|, and check !empty(FugitiveGitDir()) to confirm Fugitive has\nfound a repository.  See also |fugitive-autocommands| for other, more\nselective events.\n\nABOUT                                           *fugitive-about*\n\nGrab the latest version or report a bug on GitHub:\n\nhttps://github.com/tpope/vim-fugitive\n\n vim:tw=78:et:ft=help:norl:\n"
  },
  {
    "path": "ftdetect/fugitive.vim",
    "content": "autocmd BufReadPost *.fugitiveblame setfiletype fugitiveblame\n"
  },
  {
    "path": "ftplugin/fugitiveblame.vim",
    "content": "if exists(\"b:did_ftplugin\") || !exists(\"*FugitiveGitDir\")\n  finish\nendif\nlet b:did_ftplugin = 1\n\ncall fugitive#BlameFileType()\n"
  },
  {
    "path": "plugin/fugitive.vim",
    "content": "\" fugitive.vim - A Git wrapper so awesome, it should be illegal\n\" Maintainer:   Tim Pope <http://tpo.pe/>\n\" Version:      3.7\n\" GetLatestVimScripts: 2975 1 :AutoInstall: fugitive.vim\n\nif exists('g:loaded_fugitive')\n  finish\nendif\nlet g:loaded_fugitive = 1\n\nlet s:bad_git_dir = '/$\\|^fugitive:'\n\n\" FugitiveGitDir() returns the detected Git dir for the given buffer number,\n\" or the current buffer if no argument is passed.  This will be an empty\n\" string if no Git dir was found.  Use !empty(FugitiveGitDir()) to check if\n\" Fugitive is active in the current buffer.  Do not rely on this for direct\n\" filesystem access; use FugitiveFind('.git/whatever') instead.\nfunction! FugitiveGitDir(...) abort\n  if v:version < 704\n    return ''\n  elseif !a:0 || type(a:1) == type(0) && a:1 < 0 || a:1 is# get(v:, 'true', -1)\n    if exists('g:fugitive_event')\n      return g:fugitive_event\n    endif\n    let dir = get(b:, 'git_dir', '')\n    if empty(dir) && (empty(bufname('')) && &filetype !=# 'netrw' || &buftype =~# '^\\%(nofile\\|acwrite\\|quickfix\\|terminal\\|prompt\\)$')\n      return FugitiveExtractGitDir(getcwd())\n    elseif (!exists('b:git_dir') || b:git_dir =~# s:bad_git_dir) && &buftype =~# '^\\%(nowrite\\)\\=$'\n      let b:git_dir = FugitiveExtractGitDir(bufnr(''))\n      return b:git_dir\n    endif\n    return dir =~# s:bad_git_dir ? '' : dir\n  elseif type(a:1) == type(0) && a:1 isnot# 0\n    if a:1 == bufnr('') && (!exists('b:git_dir') || b:git_dir =~# s:bad_git_dir) && &buftype =~# '^\\%(nowrite\\)\\=$'\n      let b:git_dir = FugitiveExtractGitDir(a:1)\n    endif\n    let dir = getbufvar(a:1, 'git_dir')\n    return dir =~# s:bad_git_dir ? '' : dir\n  elseif type(a:1) == type('')\n    return substitute(s:Slash(a:1), '/$', '', '')\n  elseif type(a:1) == type({})\n    return get(a:1, 'fugitive_dir', get(a:1, 'git_dir', ''))\n  else\n    return ''\n  endif\nendfunction\n\n\" FugitiveReal() takes a fugitive:// URL and returns the corresponding path in\n\" the work tree.  This may be useful to get a cleaner path for inclusion in\n\" the statusline, for example.  Note that the file and its parent directories\n\" are not guaranteed to exist.\n\"\n\" This is intended as an abstract API to be used on any \"virtual\" path.  For a\n\" buffer named foo://bar, check for a function named FooReal(), and if it\n\" exists, call FooReal(\"foo://bar\").\nfunction! FugitiveReal(...) abort\n  let file = a:0 ? a:1 : @%\n  if type(file) ==# type({})\n    let dir = FugitiveGitDir(file)\n    let tree = s:Tree(dir)\n    return s:VimSlash(empty(tree) ? dir : tree)\n  elseif file =~# '^\\a\\a\\+:' || a:0 > 1\n    return call('fugitive#Real', [file] + a:000[1:-1])\n  elseif file =~# '^/\\|^\\a:\\|^$'\n    return file\n  else\n    return fnamemodify(file, ':p' . (file =~# '[\\/]$' ? '' : ':s?[\\/]$??'))\n  endif\nendfunction\n\n\" FugitiveFind() takes a Fugitive object and returns the appropriate Vim\n\" buffer name.  You can use this to generate Fugitive URLs (\"HEAD:README\") or\n\" to get the absolute path to a file in the Git dir (\".git/HEAD\"), the common\n\" dir (\".git/config\"), or the work tree (\":(top)Makefile\").\n\"\n\" An optional second argument provides the Git dir, or the buffer number of a\n\" buffer with a Git dir.  The default is the current buffer.\nfunction! FugitiveFind(...) abort\n  if a:0 && (type(a:1) ==# type({}) || type(a:1) ==# type(0))\n    return call('fugitive#Find', a:000[1:-1] + [FugitiveGitDir(a:1)])\n  else\n    return fugitive#Find(a:0 ? a:1 : bufnr(''), FugitiveGitDir(a:0 > 1 ? a:2 : -1))\n  endif\nendfunction\n\n\" FugitiveParse() takes a fugitive:// URL and returns a 2 element list\n\" containing an object name (\"commit:file\") and the Git dir.  It's effectively\n\" the inverse of FugitiveFind().\nfunction! FugitiveParse(...) abort\n  let path = s:Slash(a:0 ? a:1 : @%)\n  if path !~# '^fugitive://'\n    return ['', '']\n  endif\n  let [rev, dir] = fugitive#Parse(path)\n  if !empty(dir)\n    return [rev, dir]\n  endif\n  throw 'fugitive: invalid Fugitive URL ' . path\nendfunction\n\n\" FugitiveGitVersion() queries the version of Git in use.  Pass up to 3\n\" arguments to return a Boolean of whether a certain minimum version is\n\" available (FugitiveGitVersion(2,3,4) checks for 2.3.4 or higher) or no\n\" arguments to get a raw string.\nfunction! FugitiveGitVersion(...) abort\n  return call('fugitive#GitVersion', a:000)\nendfunction\n\n\" FugitiveResult() returns an object encapsulating the result of the most\n\" recent :Git command.  Will be empty if no result is available.  During a\n\" User FugitiveChanged event, this is guaranteed to correspond to the :Git\n\" command that triggered the event, or be empty if :Git was not the trigger.\n\" Pass in the name of a temp buffer to get the result object for that command\n\" instead.  Contains the following keys:\n\"\n\" * \"args\": List of command arguments, starting with the subcommand.  Will be\n\"   empty for usages like :Git --help.\n\" * \"git_dir\": Git dir of the relevant repository.\n\" * \"exit_status\": The integer exit code of the process.\n\" * \"flags\": Flags passed directly to Git, like -c and --help.\n\" * \"file\": Path to file containing command output.  Not guaranteed to exist,\n\"   so verify with filereadable() before trying to access it.\nfunction! FugitiveResult(...) abort\n  return call('fugitive#Result', a:000)\nendfunction\n\n\" FugitiveExecute() runs Git with a list of arguments and returns a dictionary\n\" with the following keys:\n\"\n\" * \"exit_status\": The integer exit code of the process.\n\" * \"stdout\": The stdout produced by the process, as a list of lines.\n\" * \"stderr\": The stdout produced by the process, as a list of lines.\n\"\n\" An optional second argument provides the Git dir, or the buffer number of a\n\" buffer with a Git dir.  The default is the current buffer.\n\"\n\" An optional final argument is a callback Funcref, for asynchronous\n\" execution.\nfunction! FugitiveExecute(args, ...) abort\n  return call('fugitive#Execute', [a:args] + a:000)\nendfunction\n\n\" FugitiveShellCommand() turns an array of arguments into a Git command string\n\" which can be executed with functions like system() and commands like :!.\n\" Integer arguments will be treated as buffer numbers, and the appropriate\n\" relative path inserted in their place.\n\"\n\" An optional second argument provides the Git dir, or the buffer number of a\n\" buffer with a Git dir.  The default is the current buffer.\nfunction! FugitiveShellCommand(...) abort\n  return call('fugitive#ShellCommand', a:000)\nendfunction\n\n\" FugitiveConfig() get returns an opaque structure that can be passed to other\n\" FugitiveConfig functions in lieu of a Git directory.  This can be faster\n\" when performing multiple config queries.  Do not rely on the internal\n\" structure of the return value as it is not guaranteed.  If you want a full\n\" dictionary of every config value, use FugitiveConfigGetRegexp('.*').\n\"\n\" An optional argument provides the Git dir, or the buffer number of a\n\" buffer with a Git dir.  The default is the current buffer.  Pass a blank\n\" string to limit to the global config.\nfunction! FugitiveConfig(...) abort\n  return call('fugitive#Config', a:000)\nendfunction\n\n\" FugitiveConfigGet() retrieves a Git configuration value.  An optional second\n\" argument can be either the object returned by FugitiveConfig(), or a Git\n\" dir or buffer number to be passed along to FugitiveConfig().\nfunction! FugitiveConfigGet(name, ...) abort\n  return get(call('FugitiveConfigGetAll', [a:name] + (a:0 ? [a:1] : [])), -1, get(a:, 2, ''))\nendfunction\n\n\" FugitiveConfigGetAll() is like FugitiveConfigGet() but returns a list of\n\" all values.\nfunction! FugitiveConfigGetAll(name, ...) abort\n  return call('fugitive#ConfigGetAll', [a:name] + a:000)\nendfunction\n\n\" FugitiveConfigGetRegexp() retrieves a dictionary of all configuration values\n\" with a key matching the given pattern.  Like git config --get-regexp, but\n\" using a Vim regexp.  Second argument has same semantics as\n\" FugitiveConfigGet().\nfunction! FugitiveConfigGetRegexp(pattern, ...) abort\n  return call('fugitive#ConfigGetRegexp', [a:pattern] + a:000)\nendfunction\n\n\" FugitiveRemoteUrl() retrieves the remote URL for the given remote name,\n\" defaulting to the current branch's remote or \"origin\" if no argument is\n\" given.  Similar to `git remote get-url`, but also attempts to resolve HTTP\n\" redirects and SSH host aliases.\n\"\n\" An optional second argument provides the Git dir, or the buffer number of a\n\" buffer with a Git dir.  The default is the current buffer.\nfunction! FugitiveRemoteUrl(...) abort\n  return call('fugitive#RemoteUrl', a:000)\nendfunction\n\n\" FugitiveRemote() returns a data structure parsed from the remote URL.\n\" For example, for remote URL \"https://me@example.com:1234/repo.git\", the\n\" returned dictionary will contain the following:\n\"\n\" * \"scheme\": \"https\"\n\" * \"authority\": \"user@example.com:1234\"\n\" * \"path\": \"/repo.git\" (for SSH URLs this may be a relative path)\n\" * \"pathname\": \"/repo.git\" (always coerced to absolute path)\n\" * \"host\": \"example.com:1234\"\n\" * \"hostname\": \"example.com\"\n\" * \"port\": \"1234\"\n\" * \"user\": \"me\"\n\" * \"path\": \"/repo.git\"\n\" * \"url\": \"https://me@example.com:1234/repo.git\"\nfunction! FugitiveRemote(...) abort\n  return call('fugitive#Remote', a:000)\nendfunction\n\n\" FugitiveDidChange() triggers a FugitiveChanged event and reloads the summary\n\" buffer for the current or given buffer number's repository.  You can also\n\" give the result of a FugitiveExecute() and that context will be made\n\" available inside the FugitiveChanged() event.\n\"\n\" Passing the special argument 0 (the number zero) softly expires summary\n\" buffers for all repositories.  This can be used after a call to system()\n\" with unclear implications.\nfunction! FugitiveDidChange(...) abort\n  return call('fugitive#DidChange', a:000)\nendfunction\n\n\" FugitiveHead() retrieves the name of the current branch. If the current HEAD\n\" is detached, FugitiveHead() will return the empty string, unless the\n\" optional argument is given, in which case the hash of the current commit\n\" will be truncated to the given number of characters.\n\"\n\" An optional second argument provides the Git dir, or the buffer number of a\n\" buffer with a Git dir.  The default is the current buffer.\nfunction! FugitiveHead(...) abort\n  if a:0 && (type(a:1) ==# type({}) || type(a:1) ==# type('') && a:1 !~# '^\\d\\+$')\n    let dir = FugitiveGitDir(a:1)\n    let arg = get(a:, 2, 0)\n  elseif a:0 > 1\n    let dir = FugitiveGitDir(a:2)\n    let arg = a:1\n  else\n    let dir = FugitiveGitDir()\n    let arg = get(a:, 1, 0)\n  endif\n  if empty(dir)\n    return ''\n  endif\n  return fugitive#Head(arg, dir)\nendfunction\n\nfunction! FugitivePath(...) abort\n  if a:0 > 2 && type(a:1) ==# type({})\n    return fugitive#Path(a:2, a:3, FugitiveGitDir(a:1))\n  elseif a:0 && type(a:1) ==# type({})\n    return FugitiveReal(a:0 > 1 ? a:2 : @%)\n  elseif a:0 > 1\n    return fugitive#Path(a:1, a:2, FugitiveGitDir(a:0 > 2 ? a:3 : -1))\n  else\n    return FugitiveReal(a:0 ? a:1 : @%)\n  endif\nendfunction\n\nfunction! FugitiveStatusline(...) abort\n  if empty(FugitiveGitDir(bufnr('')))\n    return ''\n  endif\n  return fugitive#Statusline()\nendfunction\n\nlet s:resolved_git_dirs = {}\nfunction! FugitiveActualDir(...) abort\n  let dir = call('FugitiveGitDir', a:000)\n  if empty(dir)\n    return ''\n  endif\n  if !has_key(s:resolved_git_dirs, dir)\n    let s:resolved_git_dirs[dir] = s:ResolveGitDir(dir)\n  endif\n  return empty(s:resolved_git_dirs[dir]) ? dir : s:resolved_git_dirs[dir]\nendfunction\n\nlet s:commondirs = {}\nfunction! FugitiveCommonDir(...) abort\n  let dir = call('FugitiveActualDir', a:000)\n  if empty(dir)\n    return ''\n  endif\n  if has_key(s:commondirs, dir)\n    return s:commondirs[dir]\n  endif\n  if getfsize(dir . '/HEAD') >= 10\n    let cdir = get(s:ReadFile(dir . '/commondir', 1), 0, '')\n    if cdir =~# '^/\\|^\\a:/'\n      let s:commondirs[dir] = s:Slash(FugitiveVimPath(cdir))\n    elseif len(cdir)\n      let s:commondirs[dir] = simplify(dir . '/' . cdir)\n    else\n      let s:commondirs[dir] = dir\n    endif\n  else\n    let s:commondirs[dir] = dir\n  endif\n  return s:commondirs[dir]\nendfunction\n\nfunction! FugitiveWorkTree(...) abort\n  let tree = s:Tree(FugitiveGitDir(a:0 ? a:1 : -1))\n  if tree isnot# 0 || a:0 > 1\n    return tree\n  else\n    return ''\n  endif\nendfunction\n\nfunction! FugitiveIsGitDir(...) abort\n  if !a:0 || type(a:1) !=# type('')\n    return !empty(call('FugitiveGitDir', a:000))\n  endif\n  let path = substitute(a:1, '[\\/]$', '', '') . '/'\n  return len(path) && getfsize(path.'HEAD') > 10 && (\n        \\ isdirectory(path.'objects') && isdirectory(path.'refs') ||\n        \\ getftype(path.'commondir') ==# 'file')\nendfunction\n\nfunction! s:ReadFile(path, line_count) abort\n  if v:version < 800 && !filereadable(a:path)\n    return []\n  endif\n  try\n    return readfile(a:path, 'b', a:line_count)\n  catch\n    return []\n  endtry\nendfunction\n\nlet s:worktree_for_dir = {}\nlet s:dir_for_worktree = {}\nfunction! s:Tree(path) abort\n  if a:path =~# '/\\.git$'\n    return len(a:path) ==# 5 ? '/' : a:path[0:-6]\n  elseif a:path ==# ''\n    return ''\n  endif\n  let dir = FugitiveActualDir(a:path)\n  if !has_key(s:worktree_for_dir, dir)\n    let s:worktree_for_dir[dir] = ''\n    let ext_wtc_pat = 'v:val =~# \"^\\\\s*worktreeConfig *= *\\\\%(true\\\\|yes\\\\|on\\\\|1\\\\) *$\"'\n    let config = s:ReadFile(dir . '/config', 50)\n    if len(config)\n      let ext_wtc_config = filter(copy(config), ext_wtc_pat)\n      if len(ext_wtc_config) == 1 && filereadable(dir . '/config.worktree')\n         let config += s:ReadFile(dir . '/config.worktree', 50)\n      endif\n    else\n      let worktree = fnamemodify(FugitiveVimPath(get(s:ReadFile(dir . '/gitdir', 1), '0', '')), ':h')\n      if worktree ==# '.'\n        unlet! worktree\n      endif\n      if len(filter(s:ReadFile(FugitiveCommonDir(dir) . '/config', 50), ext_wtc_pat))\n        let config = s:ReadFile(dir . '/config.worktree', 50)\n      endif\n    endif\n    if len(config)\n      let wt_config = filter(copy(config), 'v:val =~# \"^\\\\s*worktree *=\"')\n      if len(wt_config)\n        let worktree = FugitiveVimPath(matchstr(wt_config[0], '= *\\zs.*'))\n      elseif !exists('worktree')\n        call filter(config,'v:val =~# \"^\\\\s*bare *= *true *$\"')\n        if empty(config)\n          let s:worktree_for_dir[dir] = 0\n        endif\n      endif\n    endif\n    if exists('worktree')\n      let s:worktree_for_dir[dir] = s:Slash(resolve(worktree))\n      let s:dir_for_worktree[s:worktree_for_dir[dir]] = dir\n    endif\n  endif\n  if s:worktree_for_dir[dir] =~# '^\\.'\n    return simplify(dir . '/' . s:worktree_for_dir[dir])\n  else\n    return s:worktree_for_dir[dir]\n  endif\nendfunction\n\nfunction! s:CeilingDirectories() abort\n  if !exists('s:ceiling_directories')\n    let s:ceiling_directories = []\n    let resolve = 1\n    for dir in split($GIT_CEILING_DIRECTORIES, has('win32') ? ';' : ':', 1)\n      if empty(dir)\n        let resolve = 0\n      elseif resolve\n        call add(s:ceiling_directories, s:Slash(resolve(dir)))\n      else\n        call add(s:ceiling_directories, s:Slash(dir))\n      endif\n    endfor\n  endif\n  return s:ceiling_directories + get(g:, 'ceiling_directories', [s:Slash(fnamemodify(expand('~'), ':h'))])\nendfunction\n\nfunction! s:ResolveGitDir(git_dir) abort\n  let type = getftype(a:git_dir)\n  if type ==# 'dir' && FugitiveIsGitDir(a:git_dir)\n    return a:git_dir\n  elseif type ==# 'link' && FugitiveIsGitDir(a:git_dir)\n    return resolve(a:git_dir)\n  elseif type !=# ''\n    let line = get(s:ReadFile(a:git_dir, 1), 0, '')\n    let file_dir = s:Slash(FugitiveVimPath(matchstr(line, '^gitdir: \\zs.*')))\n    if file_dir !~# '^/\\|^\\a:\\|^$' && a:git_dir =~# '/\\.git$' && FugitiveIsGitDir(a:git_dir[0:-5] . file_dir)\n      return simplify(a:git_dir[0:-5] . file_dir)\n    elseif file_dir =~# '^/\\|^\\a:' && FugitiveIsGitDir(file_dir)\n      return file_dir\n    endif\n  endif\n  return ''\nendfunction\n\nfunction! FugitiveExtractGitDir(path) abort\n  if type(a:path) ==# type({})\n    return get(a:path, 'fugitive_dir', get(a:path, 'git_dir', ''))\n  elseif type(a:path) == type(0)\n    let path = s:Slash(a:path > 0 ? bufname(a:path) : bufname(''))\n    if getbufvar(a:path, '&filetype') ==# 'netrw'\n      let path = s:Slash(getbufvar(a:path, 'netrw_curdir', path))\n    endif\n  else\n    let path = s:Slash(a:path)\n  endif\n  if path =~# '^fugitive://'\n    return fugitive#Parse(path)[1]\n  elseif empty(path)\n    return ''\n  endif\n  let pre = substitute(matchstr(path, '^\\a\\a\\+\\ze:'), '^.', '\\u&', '')\n  if len(pre) && exists('*' . pre . 'Real')\n    let path = {pre}Real(path)\n  endif\n  let root = s:Slash(fnamemodify(path, ':p:h'))\n  let previous = \"\"\n  let env_git_dir = len($GIT_DIR) ? s:Slash(simplify(fnamemodify(FugitiveVimPath($GIT_DIR), ':p:s?[\\/]$??'))) : ''\n  call s:Tree(env_git_dir)\n  let ceiling_directories = s:CeilingDirectories()\n  while root !=# previous && root !~# '^$\\|^//[^/]*$'\n    if index(ceiling_directories, root) >= 0\n      break\n    endif\n    if root ==# $GIT_WORK_TREE && FugitiveIsGitDir(env_git_dir)\n      return env_git_dir\n    elseif has_key(s:dir_for_worktree, root)\n      return s:dir_for_worktree[root]\n    endif\n    let dir = substitute(root, '[\\/]$', '', '') . '/.git'\n    let resolved = s:ResolveGitDir(dir)\n    if !empty(resolved)\n      let s:resolved_git_dirs[dir] = resolved\n      return dir is# resolved || s:Tree(resolved) is# 0 ? dir : resolved\n    elseif FugitiveIsGitDir(root)\n      let s:resolved_git_dirs[root] = root\n      return root\n    endif\n    let previous = root\n    let root = fnamemodify(root, ':h')\n  endwhile\n  return ''\nendfunction\n\nfunction! FugitiveDetect(...) abort\n  if v:version < 704\n    return ''\n  endif\n  if exists('b:git_dir') && b:git_dir =~# '^$\\|' . s:bad_git_dir\n    unlet b:git_dir\n  endif\n  if !exists('b:git_dir')\n    let b:git_dir = FugitiveExtractGitDir(a:0 ? a:1 : bufnr(''))\n  endif\n  return ''\nendfunction\n\nfunction! FugitiveGitPath(path) abort\n  return s:Slash(a:path)\nendfunction\n\nif exists('+shellslash')\n\n  function! s:Slash(path) abort\n    return tr(a:path, '\\', '/')\n  endfunction\n\n  function! s:VimSlash(path) abort\n    return tr(a:path, '\\/', &shellslash ? '//' : '\\\\')\n  endfunction\n\n  function FugitiveVimPath(path) abort\n    return tr(a:path, '\\/', &shellslash ? '//' : '\\\\')\n  endfunction\n\nelse\n\n  function! s:Slash(path) abort\n    return a:path\n  endfunction\n\n  function! s:VimSlash(path) abort\n    return a:path\n  endfunction\n\n  if has('win32unix') && filereadable('/git-bash.exe')\n    function! FugitiveVimPath(path) abort\n      return substitute(a:path, '^\\(\\a\\):', '/\\l\\1', '')\n    endfunction\n  else\n    function! FugitiveVimPath(path) abort\n      return a:path\n    endfunction\n  endif\n\nendif\n\nfunction! s:ProjectionistDetect() abort\n  let file = s:Slash(get(g:, 'projectionist_file', ''))\n  let dir = FugitiveExtractGitDir(file)\n  let base = matchstr(file, '^fugitive://.\\{-\\}//\\x\\+')\n  if empty(base)\n    let base = s:Tree(dir)\n  endif\n  if !empty(base)\n    if exists('+shellslash') && !&shellslash\n      let base = tr(base, '/', '\\')\n    endif\n    let file = FugitiveFind('.git/info/projections.json', dir)\n    if filereadable(file)\n      call projectionist#append(base, file)\n    endif\n  endif\nendfunction\n\nlet s:addr_other = has('patch-8.1.560') || has('nvim-0.5.0') ? '-addr=other' : ''\nlet s:addr_tabs  = has('patch-7.4.542') ? '-addr=tabs' : ''\nlet s:addr_wins  = has('patch-7.4.542') ? '-addr=windows' : ''\n\nif exists(':G') != 2\n  command! -bang -nargs=? -range=-1 -complete=customlist,fugitive#Complete G   exe fugitive#Command(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)\nendif\ncommand! -bang -nargs=? -range=-1 -complete=customlist,fugitive#Complete Git exe fugitive#Command(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)\n\nif exists(':Gstatus') != 2 && get(g:, 'fugitive_legacy_commands', 0)\n  exe 'command! -bang -bar     -range=-1' s:addr_other 'Gstatus exe fugitive#Command(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\n        \\ '|echohl WarningMSG|echomsg \":Gstatus is deprecated in favor of :Git (with no arguments)\"|echohl NONE'\nendif\n\nfor s:cmd in ['Commit', 'Revert', 'Merge', 'Rebase', 'Pull', 'Push', 'Fetch', 'Blame']\n  if exists(':G' . tolower(s:cmd)) != 2 && get(g:, 'fugitive_legacy_commands', 0)\n    exe 'command! -bang -nargs=? -range=-1 -complete=customlist,fugitive#' . s:cmd . 'Complete G' . tolower(s:cmd)\n          \\ 'echohl WarningMSG|echomsg \":G' . tolower(s:cmd) . ' is deprecated in favor of :Git ' . tolower(s:cmd) . '\"|echohl NONE|'\n          \\ 'exe fugitive#Command(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", \"' . tolower(s:cmd) . ' \" . <q-args>)'\n  endif\nendfor\nunlet s:cmd\n\nexe \"command! -bar -bang -nargs=? -complete=customlist,fugitive#CdComplete Gcd  exe fugitive#Cd(<q-args>, 0)\"\nexe \"command! -bar -bang -nargs=? -complete=customlist,fugitive#CdComplete Glcd exe fugitive#Cd(<q-args>, 1)\"\n\nexe 'command! -bang -nargs=? -range=-1' s:addr_wins '-complete=customlist,fugitive#GrepComplete Ggrep  exe fugitive#GrepCommand(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\nexe 'command! -bang -nargs=? -range=-1' s:addr_wins '-complete=customlist,fugitive#GrepComplete Glgrep exe fugitive#GrepCommand(0, <count> > 0 ? <count> : 0, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\n\nexe 'command! -bang -nargs=? -range=-1 -complete=customlist,fugitive#LogComplete Gclog :exe fugitive#LogCommand(<line1>,<count>,+\"<range>\",<bang>0,\"<mods>\",<q-args>, \"c\")'\nexe 'command! -bang -nargs=? -range=-1 -complete=customlist,fugitive#LogComplete GcLog :exe fugitive#LogCommand(<line1>,<count>,+\"<range>\",<bang>0,\"<mods>\",<q-args>, \"c\")'\nexe 'command! -bang -nargs=? -range=-1 -complete=customlist,fugitive#LogComplete Gllog :exe fugitive#LogCommand(<line1>,<count>,+\"<range>\",<bang>0,\"<mods>\",<q-args>, \"l\")'\nexe 'command! -bang -nargs=? -range=-1 -complete=customlist,fugitive#LogComplete GlLog :exe fugitive#LogCommand(<line1>,<count>,+\"<range>\",<bang>0,\"<mods>\",<q-args>, \"l\")'\n\nexe 'command! -bar -bang -nargs=*                          -complete=customlist,fugitive#EditComplete   Ge       exe fugitive#Open(\"edit<bang>\", 0, \"<mods>\", <q-args>)'\nexe 'command! -bar -bang -nargs=*                          -complete=customlist,fugitive#EditComplete   Gedit    exe fugitive#Open(\"edit<bang>\", 0, \"<mods>\", <q-args>)'\nexe 'command! -bar -bang -nargs=*                          -complete=customlist,fugitive#EditComplete   Gpedit   exe fugitive#Open(\"pedit\", <bang>0, \"<mods>\", <q-args>)'\nexe 'command! -bar -bang -nargs=* -range=-1' s:addr_other '-complete=customlist,fugitive#EditComplete   Gsplit   exe fugitive#Open((<count> > 0 ? <count> : \"\").(<count> ? \"split\" : \"edit\"), <bang>0, \"<mods>\", <q-args>)'\nexe 'command! -bar -bang -nargs=* -range=-1' s:addr_other '-complete=customlist,fugitive#EditComplete   Gvsplit  exe fugitive#Open((<count> > 0 ? <count> : \"\").(<count> ? \"vsplit\" : \"edit!\"), <bang>0, \"<mods>\", <q-args>)'\nexe 'command! -bar -bang -nargs=* -range=-1' s:addr_tabs  '-complete=customlist,fugitive#EditComplete   Gtabedit exe fugitive#Open((<count> >= 0 ? <count> : \"\").\"tabedit\", <bang>0, \"<mods>\", <q-args>)'\nexe 'command! -bar -bang -nargs=*                          -complete=customlist,fugitive#EditComplete   Gdrop    exe fugitive#DropCommand(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\n\nif exists(':Gr') != 2\n  exe 'command! -bar -bang -nargs=* -range=-1                -complete=customlist,fugitive#ReadComplete   Gr     exe fugitive#ReadCommand(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\nendif\nexe 'command! -bar -bang -nargs=* -range=-1                -complete=customlist,fugitive#ReadComplete   Gread    exe fugitive#ReadCommand(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\n\nexe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Gdiffsplit  exe fugitive#Diffsplit(1, <bang>0, \"<mods>\", <q-args>)'\nexe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Ghdiffsplit exe fugitive#Diffsplit(0, <bang>0, \"<mods>\", <q-args>)'\nexe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Gvdiffsplit exe fugitive#Diffsplit(0, <bang>0, \"vertical <mods>\", <q-args>)'\n\nexe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Gw     exe fugitive#WriteCommand(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\nexe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Gwrite exe fugitive#WriteCommand(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\nexe 'command! -bar -bang -nargs=* -complete=customlist,fugitive#EditComplete Gwq    exe fugitive#WqCommand(   <line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\n\nexe 'command! -bar -bang -nargs=0 GRemove exe fugitive#RemoveCommand(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\nexe 'command! -bar -bang -nargs=0 GUnlink exe fugitive#UnlinkCommand(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\nexe 'command! -bar -bang -nargs=0 GDelete exe fugitive#DeleteCommand(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\nexe 'command! -bar -bang -nargs=1 -complete=customlist,fugitive#CompleteObject GMove   exe fugitive#MoveCommand(  <line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\nexe 'command! -bar -bang -nargs=1 -complete=customlist,fugitive#RenameComplete GRename exe fugitive#RenameCommand(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\nif exists(':Gremove') != 2 && get(g:, 'fugitive_legacy_commands', 0)\n  exe 'command! -bar -bang -nargs=0 Gremove exe fugitive#RemoveCommand(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\n        \\ '|echohl WarningMSG|echomsg \":Gremove is deprecated in favor of :GRemove\"|echohl NONE'\nelseif exists(':Gremove') != 2 && !exists('g:fugitive_legacy_commands')\n  exe 'command! -bar -bang -nargs=0 Gremove echoerr \":Gremove has been removed in favor of :GRemove\"'\nendif\nif exists(':Gdelete') != 2 && get(g:, 'fugitive_legacy_commands', 0)\n  exe 'command! -bar -bang -nargs=0 Gdelete exe fugitive#DeleteCommand(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\n        \\ '|echohl WarningMSG|echomsg \":Gdelete is deprecated in favor of :GDelete\"|echohl NONE'\nelseif exists(':Gdelete') != 2 && !exists('g:fugitive_legacy_commands')\n  exe 'command! -bar -bang -nargs=0 Gdelete echoerr \":Gdelete has been removed in favor of :GDelete\"'\nendif\nif exists(':Gmove') != 2 && get(g:, 'fugitive_legacy_commands', 0)\n  exe 'command! -bar -bang -nargs=1 -complete=customlist,fugitive#CompleteObject Gmove   exe fugitive#MoveCommand(  <line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\n        \\ '|echohl WarningMSG|echomsg \":Gmove is deprecated in favor of :GMove\"|echohl NONE'\nelseif exists(':Gmove') != 2 && !exists('g:fugitive_legacy_commands')\n  exe 'command! -bar -bang -nargs=? -complete=customlist,fugitive#CompleteObject Gmove'\n        \\ 'echoerr \":Gmove has been removed in favor of :GMove\"'\nendif\nif exists(':Grename') != 2 && get(g:, 'fugitive_legacy_commands', 0)\n  exe 'command! -bar -bang -nargs=1 -complete=customlist,fugitive#RenameComplete Grename exe fugitive#RenameCommand(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\n        \\ '|echohl WarningMSG|echomsg \":Grename is deprecated in favor of :GRename\"|echohl NONE'\nelseif exists(':Grename') != 2 && !exists('g:fugitive_legacy_commands')\n  exe 'command! -bar -bang -nargs=? -complete=customlist,fugitive#RenameComplete Grename'\n        \\ 'echoerr \":Grename has been removed in favor of :GRename\"'\nendif\n\nexe 'command! -bar -bang -range=-1 -nargs=* -complete=customlist,fugitive#CompleteObject GBrowse exe fugitive#BrowseCommand(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\nif exists(':Gbrowse') != 2 && get(g:, 'fugitive_legacy_commands', 0)\n  exe 'command! -bar -bang -range=-1 -nargs=* -complete=customlist,fugitive#CompleteObject Gbrowse exe fugitive#BrowseCommand(<line1>, <count>, +\"<range>\", <bang>0, \"<mods>\", <q-args>)'\n        \\ '|if <bang>1|redraw!|endif|echohl WarningMSG|echomsg \":Gbrowse is deprecated in favor of :GBrowse\"|echohl NONE'\nelseif exists(':Gbrowse') != 2 && !exists('g:fugitive_legacy_commands')\n  exe 'command! -bar -bang -range=-1 -nargs=* -complete=customlist,fugitive#CompleteObject Gbrowse'\n        \\ 'echoerr \":Gbrowse has been removed in favor of :GBrowse\"'\nendif\n\nif v:version < 704\n  finish\nendif\n\nlet g:io_fugitive = {\n      \\ 'simplify': function('fugitive#simplify'),\n      \\ 'resolve': function('fugitive#resolve'),\n      \\ 'getftime': function('fugitive#getftime'),\n      \\ 'getfsize': function('fugitive#getfsize'),\n      \\ 'getftype': function('fugitive#getftype'),\n      \\ 'filereadable': function('fugitive#filereadable'),\n      \\ 'filewritable': function('fugitive#filewritable'),\n      \\ 'isdirectory': function('fugitive#isdirectory'),\n      \\ 'getfperm': function('fugitive#getfperm'),\n      \\ 'setfperm': function('fugitive#setfperm'),\n      \\ 'readfile': function('fugitive#readfile'),\n      \\ 'writefile': function('fugitive#writefile'),\n      \\ 'glob': function('fugitive#glob'),\n      \\ 'delete': function('fugitive#delete'),\n      \\ 'Real': function('FugitiveReal')}\n\naugroup fugitive\n  autocmd!\n\n  autocmd BufNewFile,BufReadPost *\n        \\ if exists('b:git_dir') && b:git_dir =~# '^$\\|' . s:bad_git_dir |\n        \\   unlet b:git_dir |\n        \\ endif\n  autocmd FileType           netrw\n        \\ if exists('b:git_dir') && b:git_dir =~# '^$\\|' . s:bad_git_dir |\n        \\   unlet b:git_dir |\n        \\ endif\n  autocmd BufFilePost            *  unlet! b:git_dir\n\n  autocmd FileType git\n        \\ call fugitive#MapCfile()\n  autocmd FileType gitcommit\n        \\ call fugitive#MapCfile('fugitive#MessageCfile()')\n  autocmd FileType git,gitcommit\n        \\ if &foldtext ==# 'foldtext()' |\n        \\    setlocal foldtext=fugitive#Foldtext() |\n        \\ endif\n  autocmd FileType fugitive\n        \\ call fugitive#MapCfile('fugitive#PorcelainCfile()')\n  autocmd FileType gitrebase\n        \\ let &l:include = '^\\%(pick\\|squash\\|edit\\|reword\\|fixup\\|drop\\|[pserfd]\\)\\>' |\n        \\ if &l:includeexpr !~# 'Fugitive' |\n        \\   let &l:includeexpr = 'v:fname =~# ''^\\x\\{4,\\}$'' && len(FugitiveGitDir()) ? FugitiveFind(v:fname) : ' .\n        \\     (len(&l:includeexpr) ? &l:includeexpr : 'v:fname') |\n        \\ endif |\n        \\ let b:undo_ftplugin = get(b:, 'undo_ftplugin', 'exe') . '|setl inex= inc='\n\n  autocmd BufReadCmd index{,.lock} nested\n        \\ if FugitiveIsGitDir(expand('<amatch>:p:h')) |\n        \\   let b:git_dir = s:Slash(expand('<amatch>:p:h')) |\n        \\   exe fugitive#BufReadStatus(v:cmdbang) |\n        \\   echohl WarningMSG |\n        \\   echo \"fugitive: Direct editing of .git/\" . expand('%:t') . \" is deprecated\" |\n        \\   echohl NONE |\n        \\ elseif filereadable(expand('<amatch>')) |\n        \\   silent doautocmd BufReadPre |\n        \\   keepalt noautocmd read <amatch> |\n        \\   silent 1delete_ |\n        \\   silent doautocmd BufReadPost |\n        \\ else |\n        \\   silent doautocmd BufNewFile |\n        \\ endif\n\n  autocmd BufReadCmd   fugitive://*          nested exe fugitive#BufReadCmd() |\n        \\ if &path =~# '^\\.\\%(,\\|$\\)' |\n        \\   let &l:path = substitute(&path, '^\\.,\\=', '', '') |\n        \\ endif\n  autocmd BufWriteCmd  fugitive://*          nested exe fugitive#BufWriteCmd()\n  autocmd FileReadCmd  fugitive://*          nested exe fugitive#FileReadCmd()\n  autocmd FileWriteCmd fugitive://*          nested exe fugitive#FileWriteCmd()\n  if exists('##SourceCmd')\n    autocmd SourceCmd     fugitive://*       nested exe fugitive#SourceCmd()\n  endif\n\n  autocmd User Flags call Hoist('buffer', function('FugitiveStatusline'))\n\n  autocmd User ProjectionistDetect call s:ProjectionistDetect()\naugroup END\n\nnmap <script><silent> <Plug>fugitive:y<C-G> :<C-U>call setreg(v:register, fugitive#Object(@%))<CR>\nnmap <script> <Plug>fugitive: <Nop>\n\nif get(g:, 'fugitive_no_maps')\n  finish\nendif\n\nfunction! s:Map(mode, lhs, rhs, flags) abort\n  let flags = a:flags . (a:rhs =~# '<Plug>' ? '' : '<script>') . '<nowait>'\n  let head = a:lhs\n  let tail = ''\n  let keys = get(g:, a:mode.'remap', {})\n  if len(keys) && type(keys) == type({})\n    while !empty(head)\n      if has_key(keys, head)\n        let head = keys[head]\n        if empty(head)\n          return\n        endif\n        break\n      endif\n      let tail = matchstr(head, '<[^<>]*>$\\|.$') . tail\n      let head = substitute(head, '<[^<>]*>$\\|.$', '', '')\n    endwhile\n  endif\n  if empty(mapcheck(head.tail, a:mode))\n    exe a:mode.'map' flags head.tail a:rhs\n  endif\nendfunction\n\ncall s:Map('c', '<C-R><C-G>', 'fnameescape(fugitive#Object(@%))', '<expr>')\ncall s:Map('n', 'y<C-G>', ':<C-U>call setreg(v:register, fugitive#Object(@%))<CR>', '<silent>')\n"
  },
  {
    "path": "syntax/fugitive.vim",
    "content": "if exists(\"b:current_syntax\")\n  finish\nendif\n\nsyn sync fromstart\nsyn spell notoplevel\n\nsyn include @fugitiveDiff syntax/diff.vim\n\nsyn match fugitiveHeader /^[A-Z][a-z][^:]*:/\nsyn match fugitiveHeader /^Head:/ nextgroup=fugitiveHash,fugitiveSymbolicRef skipwhite\nsyn match fugitiveHeader /^Pull:\\|^Rebase:\\|^Merge:\\|^Push:/ nextgroup=fugitiveSymbolicRef skipwhite\nsyn match fugitiveHelpHeader /^Help:/ nextgroup=fugitiveHelpTag skipwhite\nsyn match fugitiveHelpTag    /\\S\\+/ contained\n\nsyn region fugitiveSection start=/^\\%(.*(\\d\\++\\=)$\\)\\@=/ contains=fugitiveHeading end=/^$/ fold\nsyn cluster fugitiveSection contains=fugitiveSection\nsyn match fugitiveHeading /^[A-Z][a-z][^:]*\\ze (\\d\\++\\=)$/ contains=fugitivePreposition contained nextgroup=fugitiveCount skipwhite\nsyn match fugitiveCount /(\\d\\++\\=)/hs=s+1,he=e-1 contained\nsyn match fugitivePreposition /\\<\\%([io]nto\\|from\\|to\\|Rebasing\\%( detached\\)\\=\\)\\>/ transparent contained nextgroup=fugitiveHash,fugitiveSymbolicRef skipwhite\n\nsyn match fugitiveInstruction /^\\l\\l\\+\\>/ contained containedin=@fugitiveSection nextgroup=fugitiveHash skipwhite\nsyn match fugitiveDone /^done\\>/ contained containedin=@fugitiveSection nextgroup=fugitiveHash skipwhite\nsyn match fugitiveStop /^stop\\>/ contained containedin=@fugitiveSection nextgroup=fugitiveHash skipwhite\nsyn match fugitiveModifier /^[MADRCU?]\\{1,2} / contained containedin=@fugitiveSection\nsyn match fugitiveSymbolicRef /\\.\\@!\\%(\\.\\.\\@!\\|[^[:space:][:cntrl:]\\:.]\\)\\+\\.\\@<!/ contained\nsyn match fugitiveHash /^\\x\\{4,\\}\\S\\@!/ contained containedin=@fugitiveSection\nsyn match fugitiveHash /\\S\\@<!\\x\\{4,\\}\\S\\@!/ contained\n\nsyn region fugitiveHunk start=/^\\%(@@\\+ -\\)\\@=/ end=/^\\%([A-Za-z?@]\\|$\\)\\@=/ contains=diffLine,diffRemoved,diffAdded,diffNoEOL containedin=@fugitiveSection fold\n\nfor s:section in ['Untracked', 'Unstaged', 'Staged']\n  exe 'syn region fugitive' . s:section . 'Section start=/^\\%(' . s:section . ' .*(\\d\\++\\=)$\\)\\@=/ contains=fugitive' . s:section . 'Heading end=/^$/ fold'\n  exe 'syn match fugitive' . s:section . 'Modifier /^[MADRCU?] / contained containedin=fugitive' . s:section . 'Section'\n  exe 'syn cluster fugitiveSection add=fugitive' . s:section . 'Section'\n  exe 'syn match fugitive' . s:section . 'Heading /^[A-Z][a-z][^:]*\\ze (\\d\\++\\=)$/ contains=fugitivePreposition contained nextgroup=fugitiveCount skipwhite'\nendfor\nunlet s:section\n\nhi def link fugitiveHelpHeader fugitiveHeader\nhi def link fugitiveHeader Label\nhi def link fugitiveHelpTag Tag\nhi def link fugitiveHeading PreProc\nhi def link fugitiveUntrackedHeading PreCondit\nhi def link fugitiveUnstagedHeading Macro\nhi def link fugitiveStagedHeading Include\nhi def link fugitiveModifier Type\nhi def link fugitiveUntrackedModifier StorageClass\nhi def link fugitiveUnstagedModifier Structure\nhi def link fugitiveStagedModifier Typedef\nhi def link fugitiveInstruction Type\nhi def link fugitiveStop Function\nhi def link fugitiveHash Identifier\nhi def link fugitiveSymbolicRef Function\nhi def link fugitiveCount Number\n\nlet b:current_syntax = \"fugitive\"\n"
  },
  {
    "path": "syntax/fugitiveblame.vim",
    "content": "if exists(\"b:current_syntax\") || !exists(\"*FugitiveGitDir\")\n  finish\nendif\n\ncall fugitive#BlameSyntax()\n\nlet b:current_syntax = \"fugitiveblame\"\n"
  }
]