Skip to content

Commit

Permalink
fix: make git fail gracefully
Browse files Browse the repository at this point in the history
  • Loading branch information
sehoffmann committed Jan 7, 2025
1 parent 5b92a50 commit 34150e5
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 19 deletions.
2 changes: 2 additions & 0 deletions dmlcloud/core/callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,8 @@ class GitDiffCallback(Callback):

def pre_run(self, pipe):
diff = git_diff()
if diff is None:
return

if pipe.checkpointing_enabled and is_root():
self._save(pipe.checkpoint_dir.path / 'git_diff.txt', diff)
Expand Down
84 changes: 65 additions & 19 deletions dmlcloud/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,18 @@ def is_setuptools_cli_script(module):
return True


def script_path():
def script_path() -> Path | None:
"""
Returns the path to the script or module that was executed.
If python runs in interactive mode, or if "-c" command line option was used, raises a RuntimeError.
Returns None if python runs in interactive mode, or if "-c" command line option was used.
Returns:
Path to the script or module that was executed or None if not available.
"""
main = sys.modules['__main__']
if not hasattr(main, '__file__'):
raise RuntimeError('script_path() is not supported in interactive mode')
return None # interactive mode

if is_setuptools_cli_script(main):
stack = traceback.extract_stack()
Expand All @@ -54,45 +58,87 @@ def script_path():
return Path(main.__file__).resolve()


def script_dir():
def script_directory() -> Path | None:
"""
Returns the directory containing the script or module that was executed.
If python runs in interactive mode, or if "-c" command line option was used, then raises RuntimeError.
Returns None if python runs in interactive mode, or if "-c" command line option was used.
Returns:
Directory containing the script or module that was executed or None if not available.
"""
return script_path().parent
file = script_path()
if file is None:
return None
else:
return file.parent


def project_dir():
def project_dir() -> Path | None:
"""
Returns the top-level directory containing the script or module that was executed.
If python runs in interactive mode, or if "-c" command line option was used, then raises RuntimeError.
Returns None if python runs in interactive mode, or if "-c" command line option was used.
Returns:
Top-level directory containing the script or module that was executed or None if not available.
"""
cur_dir = script_dir()
cur_dir = script_directory()
if cur_dir is None:
return None

while (cur_dir / '__init__.py').exists():
cur_dir = cur_dir.parent
return cur_dir


def run_in_project(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwargs):
def run_in_project(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, **kwargs) -> subprocess.CompletedProcess:
"""
Runs a command in the project directory and returns the output.
Raises:
RuntimeError: If the project directory could not be determined.
"""
cwd = project_dir()
if cwd is None:
raise RuntimeError('Could not determine project directory')
return subprocess.run(cmd, cwd=cwd, stdout=stdout, stderr=stderr, **kwargs)


def git_hash(short=False):
if short:
process = run_in_project(['git', 'rev-parse', '--short', 'HEAD'])
else:
process = run_in_project(['git', 'rev-parse', 'HEAD'])
return process.stdout.decode('utf-8').strip()
def git_hash(short=False) -> str | None:
"""
Returns the git hash of the current commit.
If git is not available or the project is not a git repository, None is returned.
Args:
short: If True, the short hash is returned.
def git_diff():
Returns:
The git hash of the current commit or None if not available.
"""
try:
if short:
process = run_in_project(['git', 'rev-parse', '--short', 'HEAD'])
else:
process = run_in_project(['git', 'rev-parse', 'HEAD'])
return process.stdout.decode('utf-8').strip()
except RuntimeError:
return None


def git_diff() -> str | None:
"""
Returns the output of `git diff -U0 --no-color HEAD`
If git is not available or the project is not a git repository, None is returned.
Returns:
The output of `git diff -U0 --no-color HEAD` or None if not available.
"""

process = run_in_project(['git', 'diff', '-U0', '--no-color', 'HEAD'])
return process.stdout.decode('utf-8').strip()
try:
process = run_in_project(['git', 'diff', '-U0', '--no-color', 'HEAD'])
return process.stdout.decode('utf-8').strip()
except RuntimeError:
return None

0 comments on commit 34150e5

Please sign in to comment.