Skip to content

Commit 6b143ce

Browse files
committed
Reworked gitFile plugin so that it does not suck anymore; Plugins can now access the global libreselery configuration object via self.getGlobals(), which is used by the gitFile plugin to identify the directory to look for files; Added file filter into gitFile plugin so that only files matching the given patterns will be blamed for information protontypes#164
1 parent 902c65f commit 6b143ce

File tree

3 files changed

+63
-33
lines changed

3 files changed

+63
-33
lines changed

libreselery/contribution_action_plugins/git_file_contribution_action.py

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ def initialize_(self, action):
4444
Returns:
4545
bool: True if successfully initialized
4646
"""
47+
self.fileFilters = action.applies_to
48+
self.directory = self.getGlobals().directory
4749
return True
4850

4951
def gather_(self, cachedContributors=[]):
@@ -99,41 +101,53 @@ def gather_(self, cachedContributors=[]):
99101
##################################################################################
100102

101103
def execGit(self):
102-
cmd = [
104+
fileFilterStr = " ".join(
105+
[
106+
"--exclude %s" % contributionTarget.target
107+
for contributionTarget in self.fileFilters
108+
]
109+
)
110+
cmds = [
103111
"git",
104112
"ls-files",
105-
"|",
106-
"while read f;",
107-
'do echo "%s$f";' % self.GITBLAMESEPERATOR,
108-
"git blame -CCC --line-porcelain $f;",
109-
"done",
113+
"--directory", ### directory to look for files
114+
self.directory,
115+
"--ignored", ### only ls files matching the excluded files (via --exclude)
116+
fileFilterStr, ### string containing patterns for all files that should be searched for
110117
]
111-
118+
cmd = " ".join(cmds)
112119
ps = subprocess.Popen(
113-
" ".join(cmd), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
120+
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
114121
)
115122
stdout, stderr = ps.communicate()
116-
117-
fileContributions = {}
118123
if not stderr:
124+
### encode output
119125
encoded = stdout.decode("utf-8")
120-
### split output for each file (we added "\n" manually to seperate each file output)
121-
fileblames = encoded.split(self.GITBLAMESEPERATOR)[
122-
1:
123-
] ### 0 entry is empty because reasons ... :D
124-
for blame in fileblames:
125-
### seperate lines into array
126-
lines = blame.split("\n")
127-
filename = lines[0]
128-
lines = lines[1:]
129-
### put lines through blameParser
130-
fileContributorDict = self.parseBlame(lines)
131-
### filter out unwanted users, for example the one git blame adds
132-
### in case there are uncommitted changes
133-
### "<not.committed.yet>", "Not Committed Yet"
134-
if "not.committed.yet" in fileContributorDict:
135-
del fileContributorDict["not.committed.yet"]
136-
fileContributions[filename] = fileContributorDict
126+
fileList = encoded.split("\n")
127+
### exec git blame for each file
128+
fileContributions = {}
129+
for file in fileList:
130+
cmd = "git blame -CCC --line-porcelain %s" % file
131+
ps = subprocess.Popen(
132+
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
133+
)
134+
stdout, stderr = ps.communicate()
135+
if not stderr:
136+
try:
137+
### this can fail when blaming binary files for example, we skip those
138+
encoded = stdout.decode("utf-8")
139+
except UnicodeDecodeError as e:
140+
continue
141+
### seperate lines into array
142+
lines = encoded.split("\n")
143+
### put lines through blameParser
144+
fileContributorDict = self.parseBlame(lines)
145+
### filter out unwanted users, for example the one git blame adds
146+
### in case there are uncommitted changes
147+
### "<not.committed.yet>", "Not Committed Yet"
148+
if "not.committed.yet" in fileContributorDict:
149+
del fileContributorDict["not.committed.yet"]
150+
fileContributions[file] = fileContributorDict
137151
return fileContributions
138152

139153
def processFileContributorDict(self, fcDict):

libreselery/contribution_distribution_engine.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def _extractContributionDomains(self, config):
1616
### read the config and parse usable objects for each domain configured
1717
domains = []
1818
for domainDict in config.contribution_domains:
19-
domain = cdetypes.ContributionDomain(domainDict)
19+
domain = cdetypes.ContributionDomain(domainDict, globalConfig=config)
2020
domains.append(domain)
2121
return domains
2222

libreselery/contribution_distribution_engine_types.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,9 @@ def __init__(self, d, domainRef):
6565
class ContributionDomain(object):
6666
"""docstrig for ClassName"""
6767

68-
def __init__(self, d):
68+
def __init__(self, d, globalConfig={}):
6969
super(ContributionDomain, self).__init__()
70+
self.globalConfig = globalConfig
7071
self.name = next(iter(d))
7172
content = d.get(self.name)
7273
# self.__dict__.update(d.get(self.name))
@@ -78,7 +79,7 @@ def __init__(self, d):
7879
def initialize_(self):
7980
### in case we have actions, prepare plugins
8081
for action in self.actions:
81-
ret = action.initialize_()
82+
ret = action.initialize_(globalConfig=self.globalConfig)
8283
if not ret:
8384
raise ImportError(
8485
"ContributionActionPlugin %s could not be initialized properly! [ret: %s]"
@@ -130,6 +131,8 @@ def __repr__(self):
130131

131132
@pluginlib.Parent("action")
132133
class ContributionActionPlugin(object):
134+
_globals_ = {}
135+
133136
def __init__(self):
134137
super(ContributionActionPlugin, self).__init__()
135138
self.debug = False
@@ -142,9 +145,18 @@ def initialize_(self, action):
142145
def gather_(self, cachedContributors=[]):
143146
pass
144147

145-
def setDebug_(self, debug):
148+
def setDebug(self, debug):
146149
self.debug = debug
147150

151+
def getDebug(self):
152+
return self.debug
153+
154+
def setGlobals(self, d):
155+
self._globals_ = d
156+
157+
def getGlobals(self):
158+
return self._globals_
159+
148160
def log(self, msg):
149161
if self.debug:
150162
print("\t[.] Plugin [%s]: '%s'" % (self._alias_, msg))
@@ -159,7 +171,8 @@ def __init__(self, d):
159171
applyLookupDict(ACTION_LOOKUP_TYPES, content, self)
160172
self.plugin = None
161173

162-
def initialize_(self):
174+
def initialize_(self, globalConfig={}):
175+
self.globalConfig = globalConfig
163176
pluginName = self.type.name
164177
### initialize/load module & plugin
165178
moduleName = "%s.%s" % (ACTION_PLUGIN_MODULE_PREFIX, pluginName)
@@ -175,7 +188,10 @@ def initialize_(self):
175188
)() ### plugins.<pluginlib.Parent>.<plugin_alias>
176189
### dirty little debug flag set for newly instanced plugin
177190
### this has to be dne in a better way but works for now
178-
self.plugin.setDebug_(self.debug)
191+
self.plugin.setDebug(self.debug)
192+
### provide all global configuration parameters
193+
### for this plugin
194+
self.plugin.setGlobals(self.globalConfig)
179195
### initialize plugin
180196
pluginInitSuccess = self.plugin.initialize_(self)
181197
return pluginInitSuccess

0 commit comments

Comments
 (0)