Describe Git Before all let Path = vital#gina#import('System.Filepath') let profile = s:new_profile() End Before let Git = vital#gina#import('Git') End Describe .new({path}) Context A normal git working tree It returns a git instance of {path} let git = Git.new(profile.valid1) " Attributes Assert KeyExists(git, 'worktree') Assert KeyExists(git, 'repository') Assert KeyExists(git, 'commondir') Assert True(islocked('git.worktree')) Assert True(islocked('git.repository')) Assert True(islocked('git.commondir')) Assert Equals(git.worktree, profile.valid1) Assert Equals(git.repository, Path.join(profile.valid1, '.git')) Assert Equals(git.commondir, '') End It returns a git instance of {path} which ends with path separator let git = Git.new(fnamemodify(profile.valid1, ':p')) " Attributes Assert KeyExists(git, 'worktree') Assert KeyExists(git, 'repository') Assert KeyExists(git, 'commondir') Assert True(islocked('git.worktree')) Assert True(islocked('git.repository')) Assert True(islocked('git.commondir')) Assert Equals(git.worktree, profile.valid1) Assert Equals(git.repository, Path.join(profile.valid1, '.git')) Assert Equals(git.commondir, '') End It returns a git instance of a worktree which {path} belongs let path1 = Path.join(profile.valid1, 'A', 'foo', 'bar.txt') let path2 = Path.join(profile.valid1, 'B', 'foo', 'bar.txt') let path3 = Path.join(profile.valid1, 'C', 'foo') let git1 = Git.new(path1) let git2 = Git.new(path2) let git3 = Git.new(path3) Assert Equals(git1.worktree, profile.valid1) Assert Equals(git1.repository, Path.join(profile.valid1, '.git')) Assert Equals(git1.commondir, '') Assert Equals(git1, git2) Assert Equals(git1, git3) End End Context A git working tree by 'git worktree' It returns a git instance of {path} if !profile.git_support_worktree Skip This git does not support 'git worktree' feature endif let git = Git.new(profile.valid2) " Attributes Assert KeyExists(git, 'worktree') Assert KeyExists(git, 'repository') Assert KeyExists(git, 'commondir') Assert True(islocked('git.worktree')) Assert True(islocked('git.repository')) Assert True(islocked('git.commondir')) Assert Equals(git.worktree, profile.valid2) Assert Equals(git.repository, Path.join( \ profile.valid1, '.git', 'worktrees', 'valid2' \)) Assert Equals(git.commondir, Path.join(profile.valid1, '.git')) End It returns a git instance of {path} which ends with path separator if !profile.git_support_worktree Skip This git does not support 'git worktree' feature endif let git = Git.new(fnamemodify(profile.valid2, ':p')) " Attributes Assert KeyExists(git, 'worktree') Assert KeyExists(git, 'repository') Assert KeyExists(git, 'commondir') Assert True(islocked('git.worktree')) Assert True(islocked('git.repository')) Assert True(islocked('git.commondir')) Assert Equals(git.worktree, profile.valid2) Assert Equals(git.repository, Path.join( \ profile.valid1, '.git', 'worktrees', 'valid2' \)) Assert Equals(git.commondir, Path.join(profile.valid1, '.git')) End It returns a git instance of a worktree which {path} belongs if !profile.git_support_worktree Skip This git does not support 'git worktree' feature endif let path1 = Path.join(profile.valid2, 'A', 'foo', 'bar.txt') let path2 = Path.join(profile.valid2, 'B', 'foo', 'bar.txt') let path3 = Path.join(profile.valid2, 'C', 'foo') let git1 = Git.new(path1) let git2 = Git.new(path2) let git3 = Git.new(path3) Assert Equals(git1.worktree, profile.valid2) Assert Equals(git1.repository, Path.join( \ profile.valid1, '.git', 'worktrees', 'valid2' \)) Assert Equals(git1.commondir, Path.join(profile.valid1, '.git')) Assert Equals(git1, git2) Assert Equals(git1, git3) End End Context A non git repository It returns an empty dictionary of {path} let git = Git.new(profile.invalid) Assert Equals(git, {}) let git = Git.new(fnamemodify(profile.invalid, ':p')) Assert Equals(git, {}) let git = Git.new(Path.join(profile.invalid, 'A', 'foo', 'bar.txt')) Assert Equals(git, {}) let git = Git.new(Path.join(profile.invalid, 'B', 'foo', 'bar.txt')) Assert Equals(git, {}) let git = Git.new(Path.join(profile.invalid, 'C', 'foo')) Assert Equals(git, {}) End End End Describe .relpath({git}, {path}) It returns a relative path of {path} in {git} repository let git = Git.new(profile.valid1) let abspath = Path.join(profile.valid1, 'A', 'foo', 'bar.txt') let relpath = Path.join('A', 'foo', 'bar.txt') Assert Equals(Git.relpath(git, abspath), relpath) End It returns {path} if {path} is already a relative path let git = Git.new(profile.valid1) let relpath = Path.join('A', 'foo', 'bar.txt') Assert Equals(Git.relpath(git, relpath), relpath) Assert Same(Git.relpath(git, relpath), relpath) End End Describe .abspath({git}, {path}) It returns an absolute path of {path} in {git} repository let git = Git.new(profile.valid1) let abspath = Path.join(profile.valid1, 'A', 'foo', 'bar.txt') let relpath = Path.join('A', 'foo', 'bar.txt') Assert Equals(Git.abspath(git, relpath), abspath) End It returns {path} if {path} is already an absolute path let git = Git.new(profile.valid1) let abspath = Path.join(profile.valid1, 'A', 'foo', 'bar.txt') Assert Equals(Git.abspath(git, abspath), abspath) Assert Same(Git.abspath(git, abspath), abspath) End End Describe .resolve({git}, {path}) It returns an absolute path of {path} in a .git directory let git = Git.new(profile.valid1) let path = Git.resolve(git, 'HEAD') Assert Equals(path, Path.join(git.repository, 'HEAD')) End End Describe .ref({git}, {refname}) Context with traditional ref Before let git = Git.new(profile.valid1) End It returns a ref (e.g. refs/heads/master) of {refname} (e.g. master) let cmd = printf('git -C %s rev-parse %%s', shellescape(git.worktree)) let hash = matchstr(system(printf(cmd, 'master')), '^\w\+') let ref = Git.ref(git, 'master') Assert Equals(ref, { \ 'path': 'refs/heads/master', \ 'name': 'master', \ 'hash': hash, \}) let ref = Git.ref(git, 'refs/heads/master') Assert Equals(ref, { \ 'path': 'refs/heads/master', \ 'name': 'master', \ 'hash': hash, \}) let ref = Git.ref(git, 'HEAD') Assert Equals(ref, { \ 'path': 'refs/heads/master', \ 'name': 'master', \ 'hash': hash, \}) let hash = matchstr(system(printf(cmd, 'develop')), '^\w\+') let ref = Git.ref(git, 'develop') Assert Equals(ref, { \ 'path': 'refs/heads/develop', \ 'name': 'develop', \ 'hash': hash, \}) let ref = Git.ref(git, 'refs/heads/develop') Assert Equals(ref, { \ 'path': 'refs/heads/develop', \ 'name': 'develop', \ 'hash': hash, \}) let ref = Git.ref(git, 'unknown') Assert Equals(ref, {}) End End Context with packed ref Before let git = Git.new(profile.valid4) End It returns a ref (e.g. refs/heads/master) of {refname} (e.g. master) let cmd = printf('git -C %s rev-parse %%s', shellescape(git.worktree)) let hash = matchstr(system(printf(cmd, 'master')), '^\w\+') let ref = Git.ref(git, 'master') Assert Equals(ref, { \ 'path': 'refs/heads/master', \ 'name': 'master', \ 'hash': hash, \}) let ref = Git.ref(git, 'refs/heads/master') Assert Equals(ref, { \ 'path': 'refs/heads/master', \ 'name': 'master', \ 'hash': hash, \}) let ref = Git.ref(git, 'HEAD') Assert Equals(ref, { \ 'path': 'refs/heads/master', \ 'name': 'master', \ 'hash': hash, \}) let hash = matchstr(system(printf(cmd, 'develop')), '^\w\+') let ref = Git.ref(git, 'develop') Assert Equals(ref, { \ 'path': 'refs/heads/develop', \ 'name': 'develop', \ 'hash': hash, \}) let ref = Git.ref(git, 'refs/heads/develop') Assert Equals(ref, { \ 'path': 'refs/heads/develop', \ 'name': 'develop', \ 'hash': hash, \}) let ref = Git.ref(git, 'unknown') Assert Equals(ref, {}) End End End End " Test profile --------------------------------------------------------------- function! s:new_profile() abort let Path = vital#gina#import('System.Filepath') let root = resolve(tempname()) let valid1 = Path.join(root, 'valid1') " Normal let valid2 = Path.join(root, 'valid2') " Worktree (git worktree) let valid3 = Path.join(root, 'valid3') " For external remote let valid4 = Path.join(root, 'valid4') " Normal with packed-ref let invalid = Path.join(root, 'invalid') " Build files and directories for path in [valid1, valid3, valid4, invalid] call mkdir(Path.join(path, 'A', 'foo'), 'p') call mkdir(Path.join(path, 'B', 'foo'), 'p') call mkdir(Path.join(path, 'C', 'foo'), 'p') call writefile(['A'], Path.join(path, 'A', 'foo', 'bar.txt')) call writefile(['B'], Path.join(path, 'B', 'foo', 'bar.txt')) call writefile(['C'], Path.join(path, 'C', 'foo', 'bar.txt')) endfor " Configure git repository let git = {} let git_version = matchstr(system('git --version'), '\%(\d\+\.\)\+\d') let git_support_worktree = git_version !~# '^\%([01]\..*\|2\.4\..*\)$' function! git.execute(...) abort let command = a:0 == 1 ? a:1 : call('printf', a:000) let args = [ \ 'git', \ '-c color.ui=false', \ '-c core.editor=false', \ '--no-pager', \] if !empty(get(self, 'worktree')) let args += ['-C', fnameescape(self.worktree)] endif return system(join(args + [command])) endfunction let git.worktree = valid1 call git.execute('init') call git.execute('add %s', fnameescape(Path.realpath('A/foo/bar.txt'))) call git.execute('commit --quiet -m "First"') call git.execute('checkout --track -b develop') call git.execute('add %s', fnameescape(Path.realpath('B/foo/bar.txt'))) call git.execute('commit --quiet -m "Second"') call git.execute('checkout master') call git.execute('add %s', fnameescape(Path.realpath('C/foo/bar.txt'))) call git.execute('commit --quiet -m "Third"') if git_support_worktree call git.execute('worktree add %s develop', fnameescape(valid2)) endif let git.worktree = valid3 call git.execute('init') call git.execute('add %s', fnameescape(Path.realpath('A/foo/bar.txt'))) call git.execute('commit --quiet -m "Fourth"') let git.worktree = valid1 call git.execute('remote add ext %s', fnameescape(valid3)) call git.execute('fetch ext') call git.execute('checkout --track -b ext/master remotes/ext/master') call git.execute('checkout master') let git.worktree = valid4 call git.execute('init') call git.execute('add %s', fnameescape(Path.realpath('A/foo/bar.txt'))) call git.execute('commit --quiet -m "First"') call git.execute('checkout --track -b develop') call git.execute('add %s', fnameescape(Path.realpath('B/foo/bar.txt'))) call git.execute('commit --quiet -m "Second"') call git.execute('checkout master') call git.execute('add %s', fnameescape(Path.realpath('C/foo/bar.txt'))) call git.execute('commit --quiet -m "Third"') call git.execute('remote add ext %s', fnameescape(valid3)) call git.execute('fetch ext') call git.execute('checkout --track -b ext/master remotes/ext/master') call git.execute('checkout master') call git.execute('gc') return { \ 'root': root, \ 'valid1': valid1, \ 'valid2': valid2, \ 'valid3': valid3, \ 'valid4': valid4, \ 'invalid': invalid, \ 'git_version': git_version, \ 'git_support_worktree': git_support_worktree, \} endfunction