Coverage for tsfpga/svn_utils.py: 67%
49 statements
« prev ^ index » next coverage.py v6.4, created at 2022-05-28 04:01 +0000
« prev ^ index » next coverage.py v6.4, created at 2022-05-28 04:01 +0000
1# --------------------------------------------------------------------------------------------------
2# Copyright (c) Lukas Vik. All rights reserved.
3#
4# This file is part of the tsfpga project.
5# https://tsfpga.com
6# https://gitlab.com/tsfpga/tsfpga
7# --------------------------------------------------------------------------------------------------
9import re
10import subprocess
12from tsfpga.system_utils import file_is_in_directory
15def get_svn_revision_information(cwd=None):
16 check_that_svn_commands_are_available(cwd)
17 result = f"r{get_svn_revision(cwd)}"
18 if svn_local_changes_are_present(cwd):
19 result += " (local changes present)"
20 return result
23def svn_commands_are_available(cwd=None):
24 try:
25 get_svn_revision(cwd)
26 except (subprocess.CalledProcessError, FileNotFoundError):
27 return False
28 return True
31def check_that_svn_commands_are_available(cwd=None):
32 if not svn_commands_are_available(cwd):
33 mesg = (
34 "Could not run svn. Is the command available on PATH? Is the script called from a repo?"
35 )
36 raise RuntimeError(mesg)
39def get_svn_revision(cwd=None):
40 command = ["svn", "info", "--show-item", "revision"]
41 output = subprocess.check_output(command, cwd=cwd, universal_newlines=True)
42 # Remove trailing newline
43 return int(output.strip())
46def svn_local_changes_are_present(cwd=None):
47 """
48 Return true if the repo contains changes that have been made after the last commit.
49 Info from here: https://rubyinrails.com/2014/01/11/svn-command-to-check-modified-files/
50 """
51 command = ["svn", "status"]
52 output = subprocess.check_output(command, cwd=cwd, universal_newlines=True)
53 # Status code for file Added, Deleted, Modified, in Conflict or missing
54 regexp = re.compile(r"\n[ADMC!] ")
55 return regexp.search(output) is not None
58RE_SVN_STATUS_LINE = re.compile(r"^.+\d+\s+\d+\s+\S+\s+(\S+)$")
61def find_svn_files(
62 directory,
63 excludes=None,
64 file_endings_include=None,
65 file_endings_avoid=None,
66):
67 """
68 Find files that are checked in to SVN. It runs "svn status" rather than "svn ls". This means
69 that it is a local operation, that does not require credentials or any connection with
70 an SVN server.
72 Arguments:
73 directory (pathlib.Path): Search in this directory.
74 excludes (list(pathlib.Path)): These files and folders will not be included.
75 file_endings_include (str or tuple(str)). Only files with these endings will be included.
76 file_endings_avoid (str or tuple(str)): String or tuple of strings. Files with these endings
77 will not be included.
79 Returns:
80 list(pathlib.Path): The files that are available in SVN.
81 """
82 excludes = [] if excludes is None else [exclude.resolve() for exclude in excludes]
84 command = ["svn", "status", "-v"]
85 output = subprocess.check_output(command, cwd=directory, universal_newlines=True)
86 for line in output.split("\n"):
87 match = RE_SVN_STATUS_LINE.match(line)
88 if not match:
89 continue
91 svn_file = match.group(1)
92 file_path = directory / svn_file
94 # Make sure concatenation of relative paths worked
95 assert file_path.exists(), file_path
97 if file_path.is_dir():
98 continue
100 if file_endings_include is not None and not file_path.name.endswith(file_endings_include):
101 continue
103 if file_endings_avoid is not None and file_path.name.endswith(file_endings_avoid):
104 continue
106 if file_is_in_directory(file_path, excludes):
107 continue
109 yield file_path