Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

"""Utilities to call Git commands.""" 

 

import os 

import logging 

from contextlib import suppress 

 

from . import common 

from .shell import call 

from .exceptions import ShellError 

 

 

log = logging.getLogger(__name__) 

 

 

def git(*args, **kwargs): 

return call('git', *args, **kwargs) 

 

 

def clone(repo, path, *, cache=None): 

"""Clone a new Git repository.""" 

log.debug("Creating a new repository...") 

 

cache = cache or os.path.expanduser("~/.gitcache") 

cache = os.path.normpath(cache) 

 

name = repo.split('/')[-1] 

27 ↛ 30line 27 didn't jump to line 30, because the condition on line 27 was never false if name.endswith(".git"): 

name = name[:-4] 

 

reference = os.path.join(cache, name + ".reference") 

if not os.path.isdir(reference): 

git('clone', '--mirror', repo, reference) 

 

git('clone', '--reference', reference, repo, os.path.normpath(path)) 

 

 

def fetch(repo, rev=None): 

"""Fetch the latest changes from the remote repository.""" 

git('remote', 'set-url', 'origin', repo) 

args = ['fetch', '--tags', '--force', '--prune', 'origin'] 

if rev: 

if len(rev) == 40: 

pass # fetch only works with a SHA if already present locally 

elif '@' in rev: 

pass # fetch doesn't work with rev-parse 

else: 

args.append(rev) 

git(*args) 

 

 

def valid(): 

"""Confirm the current directory is a valid working tree.""" 

log.debug("Checking for a valid working tree...") 

 

try: 

git('rev-parse', '--is-inside-work-tree', _show=False) 

except ShellError: 

return False 

else: 

return True 

 

 

def changes(include_untracked=False, display_status=True, _show=False): 

"""Determine if there are changes in the working tree.""" 

status = False 

 

try: 

# Refresh changes 

git('update-index', '-q', '--refresh', _show=False) 

 

# Check for uncommitted changes 

git('diff-index', '--quiet', 'HEAD', _show=_show) 

 

# Check for untracked files 

lines = git('ls-files', '--others', '--exclude-standard', _show=_show) 

 

except ShellError: 

status = True 

 

else: 

status = bool(lines) and include_untracked 

 

if status and display_status: 

with suppress(ShellError): 

lines = git('status', _show=True) 

common.show(*lines, color='git_changes') 

 

return status 

 

 

def update(rev, *, clean=True, fetch=False): # pylint: disable=redefined-outer-name 

"""Update the working tree to the specified revision.""" 

hide = {'_show': False, '_ignore': True} 

 

git('stash', **hide) 

if clean: 

git('clean', '--force', '-d', '-x', _show=False) 

 

rev = _get_sha_from_rev(rev) 

git('checkout', '--force', rev) 

git('branch', '--set-upstream-to', 'origin/' + rev, **hide) 

 

if fetch: 

# if `rev` was a branch it might be tracking something older 

git('pull', '--ff-only', '--no-rebase', **hide) 

 

 

def get_url(): 

"""Get the current repository's URL.""" 

return git('config', '--get', 'remote.origin.url', _show=False)[0] 

 

 

def get_hash(_show=False): 

"""Get the current working tree's hash.""" 

return git('rev-parse', 'HEAD', _show=_show)[0] 

 

 

def get_tag(): 

"""Get the current working tree's tag (if on a tag).""" 

return git('describe', '--tags', '--exact-match', 

_show=False, _ignore=True)[0] 

 

 

def get_branch(): 

"""Get the current working tree's branch.""" 

return git('rev-parse', '--abbrev-ref', 'HEAD', _show=False)[0] 

 

 

def _get_sha_from_rev(rev): 

"""Get a rev-parse string's hash.""" 

if '@{' in rev: # TODO: use regex for this 

parts = rev.split('@') 

branch = parts[0] 

date = parts[1].strip("{}") 

git('checkout', '--force', branch, _show=False) 

rev = git('rev-list', '-n', '1', '--before={!r}'.format(date), 

branch, _show=False)[0] 

return rev