Add check-ignore
This commit is contained in:
parent
c2f8359690
commit
8fe3e19385
107
libwyag.py
107
libwyag.py
@ -957,3 +957,110 @@ def cmd_ls_files(args):
|
||||
print(f" uid: {e.uid} group: {e.gid}")
|
||||
print(f" flags: stage={e.flag_stage} assume_valid={e.flag_assume_valid}")
|
||||
|
||||
argsp = argsubparsers.add_parser("check-ignore", help="Check path(s) against ignore rules.")
|
||||
argsp.add_argument("path", nargs="+", help="Paths to check")
|
||||
|
||||
def cmd_check_ignore(args):
|
||||
repo = repo_find()
|
||||
rules = gitignore_read(repo)
|
||||
for path in args.path:
|
||||
if check_ignore(rules, path):
|
||||
print(path)
|
||||
|
||||
def gitignore_parse1(raw):
|
||||
raw = raw.strip()
|
||||
|
||||
if not raw or raw[0] == "#":
|
||||
return None
|
||||
elif raw[0] == "!":
|
||||
return (raw[1:], False)
|
||||
elif raw[0] == "\\":
|
||||
return (raw[1:], True)
|
||||
else:
|
||||
return (raw, True)
|
||||
|
||||
def gitignore_parse(lines):
|
||||
ret = list()
|
||||
|
||||
for line in lines:
|
||||
parsed = gitignore_parse1(line)
|
||||
if parsed:
|
||||
ret.append(parsed)
|
||||
|
||||
return ret
|
||||
|
||||
class GitIgnore(object):
|
||||
absolute = None
|
||||
scoped = None
|
||||
|
||||
def __init__(self, absolute, scoped):
|
||||
self.absolute = absolute
|
||||
self.scoped = scoped
|
||||
|
||||
def gitignore_read(repo):
|
||||
ret = GitIgnore(absolute=list(), scoped=dict())
|
||||
|
||||
# Read local configuration
|
||||
repo_file = os.path.join(repo.gitdir, "info/exclude")
|
||||
if os.path.exists(repo_file):
|
||||
with open(repo_file, "r") as f:
|
||||
ret.absolute.append(gitignore_parse(f.readlines()))
|
||||
|
||||
# Global configuration
|
||||
if "XDG_CONFIG_HOME" in os.environ:
|
||||
config_home == os.environ["XDG_CONFIG_HOME"]
|
||||
else:
|
||||
config_home = os.path.expanduser("~/.config")
|
||||
global_file = os.path.join(config_home, "git/ignore")
|
||||
|
||||
if os.path.exists(global_file):
|
||||
with open(global_file, "r") as f:
|
||||
ret.absolute.append(gitignore_parse(f.readlines()))
|
||||
|
||||
# .gitignore files in the index
|
||||
index = index_read(repo)
|
||||
|
||||
for entry in index.entries:
|
||||
if entry.name == ".gitignore" or entry.name.endswith("/.gitignore"):
|
||||
dir_name = os.path.dirname(entry.name)
|
||||
contents = object_read(repo, entry.sha)
|
||||
lines = contents.blobdata.decode("utf8").splitlines()
|
||||
ret.scoped[dirname] = gitignore_parse(lines)
|
||||
return ret
|
||||
|
||||
def check_ignore1(rules, path):
|
||||
result = None
|
||||
for (pattern, value) in rules:
|
||||
if fnmatch(path, pattern):
|
||||
result = value
|
||||
return result
|
||||
|
||||
def check_ignore_scoped(rules, path):
|
||||
parent = os.path.dirname(path)
|
||||
while True:
|
||||
if parent in rules:
|
||||
result = check_ignore1(rules[parent], path)
|
||||
if result != None:
|
||||
return result
|
||||
if parent == "":
|
||||
break
|
||||
parent = os.path.dirname(parent)
|
||||
return None
|
||||
|
||||
def check_ignore_absolute(rules, path):
|
||||
parent = os.path.dirname(path)
|
||||
for ruleset in rules:
|
||||
result = check_ignore1(ruleset, path)
|
||||
if result != None:
|
||||
return result
|
||||
return False
|
||||
|
||||
def check_ignore(rules, path):
|
||||
if os.path.isabs(path):
|
||||
raise Exception("This function requires path to be relative to the repository's root")
|
||||
|
||||
result = check_ignore_scoped(rules.scoped, path)
|
||||
if result != None:
|
||||
return result
|
||||
|
||||
return check_ignore_absolute(rules.absolute, path)
|
||||
|
Loading…
Reference in New Issue
Block a user