Skip to content

Commit 67362a9

Browse files
Create function for finding all gitignored files in a folder
0 parents  commit 67362a9

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed

gitignore_plugin.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import subprocess
2+
import os
3+
4+
# Used for output suppression when calling subprocess functions; see
5+
# http://stackoverflow.com/questions/10251391/suppressing-output-in-python-subprocess-call
6+
devnull = open(os.devnull, 'w')
7+
8+
def all_ignored_files(folder):
9+
"""
10+
Returns a list (without duplicates, in the case of weird repo-nesting) of
11+
all files within the given folder that are git ignored.
12+
13+
The folder itself need not be the top level of a git repo, nor even within
14+
a git repo.
15+
"""
16+
17+
all_ignored_files = set()
18+
19+
# First find all repos CONTAINED in this folder:
20+
repos = set(find_git_repos(folder))
21+
22+
# Then, additionally, if this folder is itself contained within a repo,
23+
# find the .git folder of the repo containing it:
24+
if is_in_git_repo(folder):
25+
repos.add(parent_repo_path(folder))
26+
27+
# Now we find all the ignored files in any of the above repos
28+
for git_repo in repos:
29+
ignored_files = list_ignored_files(git_repo)
30+
all_ignored_files.update(ignored_files)
31+
32+
return list(all_ignored_files)
33+
34+
def is_in_git_repo(folder):
35+
"""
36+
Returns true if the given folder is contained within a git repo
37+
"""
38+
39+
exit_code = subprocess.call(
40+
["git", "rev-parse", "--is-inside-work-tree"],
41+
cwd=folder,
42+
stdout=devnull,
43+
stderr=devnull
44+
)
45+
46+
return exit_code == 0
47+
48+
def parent_repo_path(folder):
49+
"""
50+
Takes the path to a folder contained within a git repo, and returns the parent repo.
51+
"""
52+
53+
return subprocess.Popen(
54+
['git', 'rev-parse', '--show-toplevel'],
55+
stdout=subprocess.PIPE,
56+
cwd=folder
57+
).stdout.read().strip()
58+
59+
def find_git_repos(folder):
60+
"""
61+
Returns a list of all git repos within the given ancestor folder.
62+
"""
63+
64+
# Command for finding git repos nicked from
65+
# http://sixarm.com/about/git-how-to-find-git-repository-directories.html
66+
command_output = subprocess.Popen(
67+
['find', folder, '-type', 'd', '-name', '.git'],
68+
stdout=subprocess.PIPE
69+
).stdout.read()
70+
71+
if command_output.isspace() or command_output == '':
72+
return []
73+
74+
dot_git_folders = command_output.strip().split('\n')
75+
76+
return [path.replace('/.git', '') for path in dot_git_folders]
77+
78+
def list_ignored_files(git_repo):
79+
"""
80+
Takes the path of a git repo and lists all ignored files in the repo.
81+
"""
82+
83+
# Trick for listing ignored files nicked from
84+
# http://stackoverflow.com/a/2196755/1709587
85+
command_output = subprocess.Popen(
86+
['git', 'clean', '-ndX'],
87+
stdout=subprocess.PIPE,
88+
cwd=git_repo
89+
).stdout.read()
90+
91+
if command_output.isspace() or command_output == '':
92+
return []
93+
94+
lines = command_output.strip().split('\n')
95+
# Each line in `lines` now looks something like:
96+
# "Would remove foo/bar/yourfile.txt"
97+
98+
relative_paths = [line.replace('Would remove ', '', 1) for line in lines]
99+
absolute_paths = [git_repo + '/' + path for path in relative_paths]
100+
101+
return absolute_paths

0 commit comments

Comments
 (0)