This commit integrates the feature analysis added by the last commits. Now the tagging configurations "feature" which is a project wide feature analysis and "feature_file" for a per-file feature analysis are supported. Additionally we introduce a --tagging parameter. This parameter defaults to "default" which uses the tagging value from the configuration. Sometimes you want to use the same configuration file but with different analysis methods, this could also be useful with CI later on. Extracted LinkType class to an extra file so it can be used throughout the codebase (instead of magic strings). Signed-off-by: Matthias Dittrich <matthi.d@xxxxxxxxx> Reviewed-by: Wolfgang Mauerer <wolfgang.mauerer@xxxxxxxxxxx> --- codeface/VCS.py | 12 +++++++++--- codeface/cli.py | 7 ++++++- codeface/cluster/cluster.py | 29 ++++++++++++++++------------- codeface/linktype.py | 29 +++++++++++++++++++++++++++++ codeface/project.py | 28 +++++++++++----------------- 5 files changed, 71 insertions(+), 34 deletions(-) create mode 100644 codeface/linktype.py diff --git a/codeface/VCS.py b/codeface/VCS.py index 079be83..0190cec 100644 --- a/codeface/VCS.py +++ b/codeface/VCS.py @@ -49,7 +49,10 @@ import shutil from fileCommit import FileDict from progressbar import ProgressBar, Percentage, Bar, ETA from ctags import CTags, TagEntry -from logging import getLogger; log = getLogger(__name__) +from logging import getLogger +from codeface.linktype import LinkType + +log = getLogger(__name__) from .util import execute_command class Error(Exception): @@ -866,7 +869,7 @@ class gitVCS (VCS): self._prepareCommitLists() - if link_type in ("proximity", "file"): + if link_type in (LinkType.proximity, LinkType.file, LinkType.feature, LinkType.feature_file): self.addFiles4Analysis() self._prepareFileCommitList(self._fileNames, link_type=link_type) @@ -1096,8 +1099,11 @@ class gitVCS (VCS): file_commit.addFileSnapShot(rev, cmt_lines) # locate all function lines in the file - if link_type=="proximity": # separate the file commits into code structures + if link_type == LinkType.proximity: # separate the file commits into code structures self._getFunctionLines(src_lines, file_commit) + elif link_type in (LinkType.feature_file, LinkType.feature): + self._get_feature_lines(src_lines, file_commit) + # else: do not separate file commits into code structures, # this will result in all commits to a single file seen as # related thus the more course grained analysis diff --git a/codeface/cli.py b/codeface/cli.py index 708b6b5..7c774e0 100644 --- a/codeface/cli.py +++ b/codeface/cli.py @@ -56,6 +56,11 @@ def get_parser(): run_parser.set_defaults(func=cmd_run) run_parser.add_argument('-c', '--config', help="Prosoda configuration file", default='codeface.conf') + run_parser.add_argument( + '--tagging', + help="Overrides the tagging configuration within the CLI. " + "When used this parameter overrides the configured tagging, default is fallback to configuration value", + default='default') run_parser.add_argument('-p', '--project', help="Project configuration file", required=True) run_parser.add_argument('resdir', @@ -103,7 +108,7 @@ def cmd_run(args): logfile = os.path.abspath(logfile) project_analyse(resdir, gitdir, codeface_conf, project_conf, args.no_report, args.loglevel, logfile, args.recreate, - args.profile_r, args.jobs) + args.profile_r, args.jobs, args.tagging) return 0 def cmd_ml(args): diff --git a/codeface/cluster/cluster.py b/codeface/cluster/cluster.py index 542275c..0139284 100755 --- a/codeface/cluster/cluster.py +++ b/codeface/cluster/cluster.py @@ -39,18 +39,11 @@ from codeface.VCS import gitVCS from codeface.dbmanager import DBManager, tstamp_to_sql from .PersonInfo import PersonInfo from .idManager import idManager +from codeface.linktype import LinkType #Global Constants SEED = 448 -#enum-like class to distinguish between the various -#methods used to link individuals -class LinkType: - tag = "tag" - proximity = "proximity" - committer2author = "committer2author" - file = "file" - def createDB(filename, git_repo, revrange, subsys_descr, link_type, range_by_date, rcranges=None): @@ -1666,17 +1659,27 @@ def performAnalysis(conf, dbm, dbfilename, git_repo, revrange, subsys_descr, elif link_type == LinkType.committer2author: computeCommitterAuthorLinks(cmtlist, id_mgr) - elif link_type in (LinkType.proximity, LinkType.file): + elif link_type in (LinkType.proximity, LinkType.file, LinkType.feature, LinkType.feature_file): if limit_history: startDate = git.getRevStartDate() else: startDate = None fileCommitDict = git.getFileCommitDict() - computeProximityLinks(fileCommitDict, cmtdict, id_mgr, link_type, - startDate) - logical_depends = computeLogicalDepends(fileCommitDict, cmtdict, - startDate) + logical_depends = None + if link_type == LinkType.proximity: + computeProximityLinks( + fileCommitDict, cmtdict, id_mgr, link_type, startDate) + logical_depends = \ + computeLogicalDepends(fileCommitDict, cmtdict, startDate) + elif link_type == LinkType.feature_file: + compute_feature_proximity_links_per_file( + fileCommitDict, cmtdict, id_mgr, link_type, startDate) + elif link_type == LinkType.feature: + compute_feature_proximity_links( + fileCommitDict, cmtdict, id_mgr, link_type, startDate) + else: + raise Exception("Unsupported collaboration type!") #--------------------------------- #compute statistical information #--------------------------------- diff --git a/codeface/linktype.py b/codeface/linktype.py new file mode 100644 index 0000000..b145067 --- /dev/null +++ b/codeface/linktype.py @@ -0,0 +1,29 @@ +## This file is part of Codeface. Codeface is free software: you can +## redistribute it and/or modify it under the terms of the GNU General Public +## License as published by the Free Software Foundation, version 2. +## +## This program is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +## FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +## +## Copyright 2013 by Siemens AG, Wolfgang Mauerer <wolfgang.mauerer@xxxxxxxxxxx> +## Copyright 2014 by Matthias Dittrich <matthi.d@xxxxxxxxx> +## All Rights Reserved. + +__author__ = 'drag0on' + + +#enum-like class to distinguish between the various +#methods used to link individuals +class LinkType: + tag = "tag" + proximity = "proximity" + committer2author = "committer2author" + file = "file" + feature = "feature" + feature_file = "feature_file" diff --git a/codeface/project.py b/codeface/project.py index 1d8c0b6..fd93957 100644 --- a/codeface/project.py +++ b/codeface/project.py @@ -20,7 +20,7 @@ from os.path import join as pathjoin, split as pathsplit, abspath from .dbmanager import DBManager from .configuration import Configuration -from .cluster.cluster import doProjectAnalysis +from .cluster.cluster import doProjectAnalysis, LinkType from .ts import dispatch_ts_analysis from .util import (execute_command, generate_reports, layout_graph, check4ctags, check4cppstats, BatchJobPool, generate_analysis_windows) @@ -51,21 +51,16 @@ def project_setup(conf, recreate): return project_id, dbm, all_range_ids def project_analyse(resdir, gitdir, codeface_conf, project_conf, - no_report, loglevel, logfile, recreate, profile_r, n_jobs): + no_report, loglevel, logfile, recreate, profile_r, n_jobs, tagging_type): pool = BatchJobPool(int(n_jobs)) conf = Configuration.load(codeface_conf, project_conf) tagging = conf["tagging"] - if collab_type is not "default": - # as collab_type is ignored on some tagging values we should either - # => throw an exception to tell the user he specified something weird - # => set tagging to something valid - if tagging is not "proximity": - log.warn("tagging value is overwritten to proximity because of --collaboration") - tagging = "proximity" + if tagging_type is not "default": + # we override the configuration value + if tagging is not tagging_type: + log.warn("tagging value is overwritten to {0} because of --tagging".format(tagging_type)) + tagging = tagging_type conf["tagging"] = tagging - else: - # default is function - collab_type = "function" project = conf["project"] repo = pathjoin(gitdir, conf["repo"], ".git") @@ -80,11 +75,10 @@ def project_analyse(resdir, gitdir, codeface_conf, project_conf, range_by_date = True # TODO: Sanity checks (ensure that git repo dir exists) - if 'proximity' == tagging: - if collab_type is 'function': - check4ctags() - else: - check4cppstats() + if tagging == LinkType.proximity: + check4ctags() + elif tagging in (LinkType.feature, LinkType.feature_file): + check4cppstats() project_id, dbm, all_range_ids = project_setup(conf, recreate) -- 1.8.5.5