1- """Utilities for verifying git integrity ."""
1+ """Git utilities ."""
22
33# Used also from setup.py, so don't pull in anything additional here (like mypy or typing):
44import os
5- import pipes
65import subprocess
7- import sys
8-
9- MYPY = False
10- if MYPY :
11- from typing import Iterator
126
137
148def is_git_repo (dir : str ) -> bool :
@@ -27,36 +21,11 @@ def have_git() -> bool:
2721 return False
2822
2923
30- def get_submodules (dir : str ) -> "Iterator[str]" :
31- """Return a list of all git top-level submodules in a given directory."""
32- # It would be nicer to do
33- # "git submodule foreach 'echo MODULE $name $path $sha1 $toplevel'"
34- # but that wouldn't work on Windows.
35- output = subprocess .check_output (["git" , "submodule" , "status" ], cwd = dir )
36- # "<status><sha1> name desc"
37- # status='-': not initialized
38- # status='+': changed
39- # status='u': merge conflicts
40- # status=' ': up-to-date
41- for line in output .splitlines ():
42- # Skip the status indicator, as it could be a space can confuse the split.
43- line = line [1 :]
44- name = line .split (b" " )[1 ]
45- yield name .decode (sys .getfilesystemencoding ())
46-
47-
4824def git_revision (dir : str ) -> bytes :
4925 """Get the SHA-1 of the HEAD of a git repository."""
5026 return subprocess .check_output (["git" , "rev-parse" , "HEAD" ], cwd = dir ).strip ()
5127
5228
53- def submodule_revision (dir : str , submodule : str ) -> bytes :
54- """Get the SHA-1 a submodule is supposed to have."""
55- output = subprocess .check_output (["git" , "ls-files" , "-s" , submodule ], cwd = dir ).strip ()
56- # E.g.: "160000 e4a7edb949e0b920b16f61aeeb19fc3d328f3012 0 typeshed"
57- return output .split ()[1 ]
58-
59-
6029def is_dirty (dir : str ) -> bool :
6130 """Check whether a git repository has uncommitted changes."""
6231 output = subprocess .check_output (["git" , "status" , "-uno" , "--porcelain" ], cwd = dir )
@@ -67,74 +36,3 @@ def has_extra_files(dir: str) -> bool:
6736 """Check whether a git repository has untracked files."""
6837 output = subprocess .check_output (["git" , "clean" , "--dry-run" , "-d" ], cwd = dir )
6938 return output .strip () != b""
70-
71-
72- def warn_no_git_executable () -> None :
73- print ("Warning: Couldn't check git integrity. "
74- "git executable not in path." , file = sys .stderr )
75-
76-
77- def warn_dirty (dir : str ) -> None :
78- print ("Warning: git module '{}' has uncommitted changes." .format (dir ),
79- file = sys .stderr )
80- print ("Go to the directory" , file = sys .stderr )
81- print (" {}" .format (dir ), file = sys .stderr )
82- print ("and commit or reset your changes" , file = sys .stderr )
83-
84-
85- def warn_extra_files (dir : str ) -> None :
86- print ("Warning: git module '{}' has untracked files." .format (dir ),
87- file = sys .stderr )
88- print ("Go to the directory" , file = sys .stderr )
89- print (" {}" .format (dir ), file = sys .stderr )
90- print ("and add & commit your new files." , file = sys .stderr )
91-
92-
93- def chdir_prefix (dir : str ) -> str :
94- """Return the command to change to the target directory, plus '&&'."""
95- if os .path .relpath (dir ) != "." :
96- return "cd " + pipes .quote (dir ) + " && "
97- else :
98- return ""
99-
100-
101- def error_submodule_not_initialized (name : str , dir : str ) -> None :
102- print ("Submodule '{}' not initialized." .format (name ), file = sys .stderr )
103- print ("Please run:" , file = sys .stderr )
104- print (" {}git submodule update --init {}" .format (
105- chdir_prefix (dir ), name ), file = sys .stderr )
106-
107-
108- def error_submodule_not_updated (name : str , dir : str ) -> None :
109- print ("Submodule '{}' not updated." .format (name ), file = sys .stderr )
110- print ("Please run:" , file = sys .stderr )
111- print (" {}git submodule update {}" .format (
112- chdir_prefix (dir ), name ), file = sys .stderr )
113- print ("(If you got this message because you updated {} yourself" .format (name ), file = sys .stderr )
114- print (" then run \" git add {}\" to silence this check)" .format (name ), file = sys .stderr )
115-
116-
117- def verify_git_integrity_or_abort (datadir : str ) -> None :
118- """Verify the (submodule) integrity of a git repository.
119-
120- Potentially output warnings/errors (to stderr), and exit with status 1
121- if we detected a severe problem.
122- """
123- datadir = datadir or '.'
124- if not is_git_repo (datadir ):
125- return
126- if not have_git ():
127- warn_no_git_executable ()
128- return
129- for submodule in get_submodules (datadir ):
130- submodule_path = os .path .join (datadir , submodule )
131- if not is_git_repo (submodule_path ):
132- error_submodule_not_initialized (submodule , datadir )
133- sys .exit (1 )
134- elif submodule_revision (datadir , submodule ) != git_revision (submodule_path ):
135- error_submodule_not_updated (submodule , datadir )
136- sys .exit (1 )
137- elif is_dirty (submodule_path ):
138- warn_dirty (submodule )
139- elif has_extra_files (submodule_path ):
140- warn_extra_files (submodule )
0 commit comments