support bool or list for hide_project_names config
This commit is contained in:
parent
71d5eef12a
commit
ae2ac14a9f
13 changed files with 78 additions and 44 deletions
|
@ -60,7 +60,7 @@ format. An example config file with all available options::
|
||||||
[settings]
|
[settings]
|
||||||
debug = false
|
debug = false
|
||||||
api_key = your-api-key
|
api_key = your-api-key
|
||||||
hide_filenames = false
|
hide_file_names = false
|
||||||
hide_project_names = false
|
hide_project_names = false
|
||||||
exclude =
|
exclude =
|
||||||
^COMMIT_EDITMSG$
|
^COMMIT_EDITMSG$
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[settings]
|
[settings]
|
||||||
debug = false
|
debug = false
|
||||||
api_key = 033c47c9-0441-4eb5-8b3f-b51f27b31049
|
api_key = 033c47c9-0441-4eb5-8b3f-b51f27b31049
|
||||||
hide_filenames =
|
hide_file_names =
|
||||||
missingfile
|
missingfile
|
||||||
python\.py$
|
python\.py$
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[settings]
|
[settings]
|
||||||
debug = false
|
debug = false
|
||||||
api_key = 033c47c9-0441-4eb5-8b3f-b51f27b31049
|
api_key = 033c47c9-0441-4eb5-8b3f-b51f27b31049
|
||||||
hide_filenames = invalid(regex
|
hide_file_names = invalid(regex
|
||||||
|
|
|
@ -12,4 +12,4 @@ include =
|
||||||
\(invalid regex)
|
\(invalid regex)
|
||||||
includeme
|
includeme
|
||||||
offline = true
|
offline = true
|
||||||
hide_filenames = true
|
hide_file_names = true
|
||||||
|
|
|
@ -3,7 +3,7 @@ usage: wakatime [-h] [--entity FILE] [--key KEY] [--write] [--plugin PLUGIN]
|
||||||
[--entity-type ENTITY_TYPE] [--category CATEGORY]
|
[--entity-type ENTITY_TYPE] [--category CATEGORY]
|
||||||
[--proxy PROXY] [--no-ssl-verify] [--project PROJECT]
|
[--proxy PROXY] [--no-ssl-verify] [--project PROJECT]
|
||||||
[--alternate-project ALTERNATE_PROJECT] [--language LANGUAGE]
|
[--alternate-project ALTERNATE_PROJECT] [--language LANGUAGE]
|
||||||
[--hostname HOSTNAME] [--disable-offline] [--hide-filenames]
|
[--hostname HOSTNAME] [--disable-offline] [--hide-file-names]
|
||||||
[--hide-project-names] [--exclude EXCLUDE]
|
[--hide-project-names] [--exclude EXCLUDE]
|
||||||
[--exclude-unknown-project] [--include INCLUDE]
|
[--exclude-unknown-project] [--include INCLUDE]
|
||||||
[--include-only-with-project-file] [--extra-heartbeats]
|
[--include-only-with-project-file] [--extra-heartbeats]
|
||||||
|
|
|
@ -3,7 +3,7 @@ usage: wakatime [-h] [--entity FILE] [--key KEY] [--write] [--plugin PLUGIN]
|
||||||
[--entity-type ENTITY_TYPE] [--category CATEGORY]
|
[--entity-type ENTITY_TYPE] [--category CATEGORY]
|
||||||
[--proxy PROXY] [--no-ssl-verify] [--project PROJECT]
|
[--proxy PROXY] [--no-ssl-verify] [--project PROJECT]
|
||||||
[--alternate-project ALTERNATE_PROJECT] [--language LANGUAGE]
|
[--alternate-project ALTERNATE_PROJECT] [--language LANGUAGE]
|
||||||
[--hostname HOSTNAME] [--disable-offline] [--hide-filenames]
|
[--hostname HOSTNAME] [--disable-offline] [--hide-file-names]
|
||||||
[--hide-project-names] [--exclude EXCLUDE]
|
[--hide-project-names] [--exclude EXCLUDE]
|
||||||
[--exclude-unknown-project] [--include INCLUDE]
|
[--exclude-unknown-project] [--include INCLUDE]
|
||||||
[--include-only-with-project-file] [--extra-heartbeats]
|
[--include-only-with-project-file] [--extra-heartbeats]
|
||||||
|
|
|
@ -3,7 +3,7 @@ usage: wakatime [-h] [--entity FILE] [--key KEY] [--write] [--plugin PLUGIN]
|
||||||
[--entity-type ENTITY_TYPE] [--category CATEGORY]
|
[--entity-type ENTITY_TYPE] [--category CATEGORY]
|
||||||
[--proxy PROXY] [--no-ssl-verify] [--project PROJECT]
|
[--proxy PROXY] [--no-ssl-verify] [--project PROJECT]
|
||||||
[--alternate-project ALTERNATE_PROJECT] [--language LANGUAGE]
|
[--alternate-project ALTERNATE_PROJECT] [--language LANGUAGE]
|
||||||
[--hostname HOSTNAME] [--disable-offline] [--hide-filenames]
|
[--hostname HOSTNAME] [--disable-offline] [--hide-file-names]
|
||||||
[--hide-project-names] [--exclude EXCLUDE]
|
[--hide-project-names] [--exclude EXCLUDE]
|
||||||
[--exclude-unknown-project] [--include INCLUDE]
|
[--exclude-unknown-project] [--include INCLUDE]
|
||||||
[--include-only-with-project-file] [--extra-heartbeats]
|
[--include-only-with-project-file] [--extra-heartbeats]
|
||||||
|
|
|
@ -3,7 +3,7 @@ usage: wakatime [-h] [--entity FILE] [--key KEY] [--write] [--plugin PLUGIN]
|
||||||
[--entity-type ENTITY_TYPE] [--category CATEGORY]
|
[--entity-type ENTITY_TYPE] [--category CATEGORY]
|
||||||
[--proxy PROXY] [--no-ssl-verify] [--project PROJECT]
|
[--proxy PROXY] [--no-ssl-verify] [--project PROJECT]
|
||||||
[--alternate-project ALTERNATE_PROJECT] [--language LANGUAGE]
|
[--alternate-project ALTERNATE_PROJECT] [--language LANGUAGE]
|
||||||
[--hostname HOSTNAME] [--disable-offline] [--hide-filenames]
|
[--hostname HOSTNAME] [--disable-offline] [--hide-file-names]
|
||||||
[--hide-project-names] [--exclude EXCLUDE]
|
[--hide-project-names] [--exclude EXCLUDE]
|
||||||
[--exclude-unknown-project] [--include INCLUDE]
|
[--exclude-unknown-project] [--include INCLUDE]
|
||||||
[--include-only-with-project-file] [--extra-heartbeats]
|
[--include-only-with-project-file] [--extra-heartbeats]
|
||||||
|
@ -49,7 +49,7 @@ optional arguments:
|
||||||
--hostname HOSTNAME Hostname of current machine.
|
--hostname HOSTNAME Hostname of current machine.
|
||||||
--disable-offline Disables offline time logging instead of queuing
|
--disable-offline Disables offline time logging instead of queuing
|
||||||
logged time.
|
logged time.
|
||||||
--hide-filenames Obfuscate filenames. Will not send file names to api.
|
--hide-file-names Obfuscate filenames. Will not send file names to api.
|
||||||
--hide-project-names Obfuscate project names. When a project folder is
|
--hide-project-names Obfuscate project names. When a project folder is
|
||||||
detected instead of using the folder name as the
|
detected instead of using the folder name as the
|
||||||
project, a .wakatime-project file is created with a
|
project, a .wakatime-project file is created with a
|
||||||
|
|
|
@ -414,7 +414,7 @@ class ConfigsTestCase(TestCase):
|
||||||
self.assertSessionCacheSaved()
|
self.assertSessionCacheSaved()
|
||||||
|
|
||||||
@log_capture()
|
@log_capture()
|
||||||
def test_does_not_hide_filenames_from_invalid_regex(self, logs):
|
def test_does_not_hide_file_names_from_invalid_regex(self, logs):
|
||||||
logging.disable(logging.NOTSET)
|
logging.disable(logging.NOTSET)
|
||||||
|
|
||||||
self.patched['wakatime.packages.requests.adapters.HTTPAdapter.send'].return_value = CustomResponse()
|
self.patched['wakatime.packages.requests.adapters.HTTPAdapter.send'].return_value = CustomResponse()
|
||||||
|
@ -434,9 +434,9 @@ class ConfigsTestCase(TestCase):
|
||||||
self.assertNothingPrinted()
|
self.assertNothingPrinted()
|
||||||
|
|
||||||
actual = self.getLogOutput(logs)
|
actual = self.getLogOutput(logs)
|
||||||
expected = u('WakaTime WARNING Regex error (unbalanced parenthesis) for include pattern: invalid(regex')
|
expected = u('WakaTime WARNING Regex error (unbalanced parenthesis) for hide_file_names pattern: invalid(regex')
|
||||||
if self.isPy35OrNewer:
|
if self.isPy35OrNewer:
|
||||||
expected = 'WakaTime WARNING Regex error (missing ), unterminated subpattern at position 7) for include pattern: invalid(regex'
|
expected = 'WakaTime WARNING Regex error (missing ), unterminated subpattern at position 7) for hide_file_names pattern: invalid(regex'
|
||||||
self.assertEquals(expected, actual)
|
self.assertEquals(expected, actual)
|
||||||
|
|
||||||
heartbeat = {
|
heartbeat = {
|
||||||
|
|
|
@ -17,7 +17,8 @@ class HeartbeatTestCase(TestCase):
|
||||||
|
|
||||||
class Args(object):
|
class Args(object):
|
||||||
exclude = []
|
exclude = []
|
||||||
hide_filenames = ['.*']
|
hide_file_names = ['.*']
|
||||||
|
hide_project_names = []
|
||||||
include = []
|
include = []
|
||||||
plugin = None
|
plugin = None
|
||||||
include_only_with_project_file = None
|
include_only_with_project_file = None
|
||||||
|
@ -50,7 +51,8 @@ class HeartbeatTestCase(TestCase):
|
||||||
|
|
||||||
class Args(object):
|
class Args(object):
|
||||||
exclude = []
|
exclude = []
|
||||||
hide_filenames = []
|
hide_file_names = []
|
||||||
|
hide_project_names = []
|
||||||
include = []
|
include = []
|
||||||
plugin = None
|
plugin = None
|
||||||
include_only_with_project_file = None
|
include_only_with_project_file = None
|
||||||
|
@ -74,7 +76,8 @@ class HeartbeatTestCase(TestCase):
|
||||||
logging.disable(logging.NOTSET)
|
logging.disable(logging.NOTSET)
|
||||||
|
|
||||||
class Args(object):
|
class Args(object):
|
||||||
hide_filenames = ['.*']
|
hide_file_names = ['.*']
|
||||||
|
hide_project_names = []
|
||||||
plugin = None
|
plugin = None
|
||||||
|
|
||||||
branch = 'abc123'
|
branch = 'abc123'
|
||||||
|
@ -95,7 +98,8 @@ class HeartbeatTestCase(TestCase):
|
||||||
logging.disable(logging.NOTSET)
|
logging.disable(logging.NOTSET)
|
||||||
|
|
||||||
class Args(object):
|
class Args(object):
|
||||||
hide_filenames = ['.*']
|
hide_file_names = ['.*']
|
||||||
|
hide_project_names = []
|
||||||
plugin = None
|
plugin = None
|
||||||
|
|
||||||
branch = 'abc123'
|
branch = 'abc123'
|
||||||
|
|
|
@ -126,10 +126,13 @@ def parse_arguments():
|
||||||
parser.add_argument('--disableoffline', dest='offline_deprecated',
|
parser.add_argument('--disableoffline', dest='offline_deprecated',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help=argparse.SUPPRESS)
|
help=argparse.SUPPRESS)
|
||||||
parser.add_argument('--hide-filenames', dest='hide_filenames',
|
parser.add_argument('--hide-file-names', dest='hide_file_names',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Obfuscate filenames. Will not send file names ' +
|
help='Obfuscate filenames. Will not send file names ' +
|
||||||
'to api.')
|
'to api.')
|
||||||
|
parser.add_argument('--hide-filenames', dest='hide_filenames',
|
||||||
|
action='store_true',
|
||||||
|
help=argparse.SUPPRESS)
|
||||||
parser.add_argument('--hidefilenames', dest='hidefilenames',
|
parser.add_argument('--hidefilenames', dest='hidefilenames',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help=argparse.SUPPRESS)
|
help=argparse.SUPPRESS)
|
||||||
|
@ -256,26 +259,8 @@ def parse_arguments():
|
||||||
pass
|
pass
|
||||||
if not args.exclude_unknown_project and configs.has_option('settings', 'exclude_unknown_project'):
|
if not args.exclude_unknown_project and configs.has_option('settings', 'exclude_unknown_project'):
|
||||||
args.exclude_unknown_project = configs.getboolean('settings', 'exclude_unknown_project')
|
args.exclude_unknown_project = configs.getboolean('settings', 'exclude_unknown_project')
|
||||||
if not args.hide_filenames and args.hidefilenames:
|
boolean_or_list('hide_file_names', args, configs, alternative_names=['hide_filenames', 'hidefilenames'])
|
||||||
args.hide_filenames = args.hidefilenames
|
boolean_or_list('hide_project_names', args, configs, alternative_names=['hide_projectnames', 'hideprojectnames'])
|
||||||
if args.hide_filenames:
|
|
||||||
args.hide_filenames = ['.*']
|
|
||||||
else:
|
|
||||||
args.hide_filenames = []
|
|
||||||
option = None
|
|
||||||
if configs.has_option('settings', 'hidefilenames'):
|
|
||||||
option = configs.get('settings', 'hidefilenames')
|
|
||||||
if configs.has_option('settings', 'hide_filenames'):
|
|
||||||
option = configs.get('settings', 'hide_filenames')
|
|
||||||
if option is not None:
|
|
||||||
if option.strip().lower() == 'true':
|
|
||||||
args.hide_filenames = ['.*']
|
|
||||||
elif option.strip().lower() != 'false':
|
|
||||||
for pattern in option.split("\n"):
|
|
||||||
if pattern.strip() != '':
|
|
||||||
args.hide_filenames.append(pattern)
|
|
||||||
if not args.hide_project_names and configs.has_option('settings', 'hide_project_names'):
|
|
||||||
args.hide_project_names = configs.getboolean('settings', 'hide_project_names')
|
|
||||||
if args.offline_deprecated:
|
if args.offline_deprecated:
|
||||||
args.offline = False
|
args.offline = False
|
||||||
if args.offline and configs.has_option('settings', 'offline'):
|
if args.offline and configs.has_option('settings', 'offline'):
|
||||||
|
@ -316,3 +301,30 @@ def parse_arguments():
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
|
|
||||||
return args, configs
|
return args, configs
|
||||||
|
|
||||||
|
|
||||||
|
def boolean_or_list(config_name, args, configs, alternative_names=[]):
|
||||||
|
"""Get a boolean or list of regexes from args and configs."""
|
||||||
|
|
||||||
|
# when argument flag present, set to wildcard regex
|
||||||
|
for key in alternative_names:
|
||||||
|
if hasattr(args, key) and getattr(args, key):
|
||||||
|
setattr(args, config_name, ['.*'])
|
||||||
|
return
|
||||||
|
|
||||||
|
setattr(args, config_name, [])
|
||||||
|
|
||||||
|
option = None
|
||||||
|
alternative_names.insert(0, config_name)
|
||||||
|
for key in alternative_names:
|
||||||
|
if configs.has_option('settings', key):
|
||||||
|
option = configs.get('settings', key)
|
||||||
|
break
|
||||||
|
|
||||||
|
if option is not None:
|
||||||
|
if option.strip().lower() == 'true':
|
||||||
|
setattr(args, config_name, ['.*'])
|
||||||
|
elif option.strip().lower() != 'false':
|
||||||
|
for pattern in option.split("\n"):
|
||||||
|
if pattern.strip() != '':
|
||||||
|
getattr(args, config_name).append(pattern)
|
||||||
|
|
|
@ -132,7 +132,7 @@ class Heartbeat(object):
|
||||||
Returns a Heartbeat.
|
Returns a Heartbeat.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not self.args.hide_filenames:
|
if not self.args.hide_file_names:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
if self.entity is None:
|
if self.entity is None:
|
||||||
|
@ -141,7 +141,7 @@ class Heartbeat(object):
|
||||||
if self.type != 'file':
|
if self.type != 'file':
|
||||||
return self
|
return self
|
||||||
|
|
||||||
for pattern in self.args.hide_filenames:
|
for pattern in self.args.hide_file_names:
|
||||||
try:
|
try:
|
||||||
compiled = re.compile(pattern, re.IGNORECASE)
|
compiled = re.compile(pattern, re.IGNORECASE)
|
||||||
if compiled.search(self.entity):
|
if compiled.search(self.entity):
|
||||||
|
@ -160,7 +160,7 @@ class Heartbeat(object):
|
||||||
return self.update(sanitized)
|
return self.update(sanitized)
|
||||||
|
|
||||||
except re.error as ex:
|
except re.error as ex:
|
||||||
log.warning(u('Regex error ({msg}) for include pattern: {pattern}').format(
|
log.warning(u('Regex error ({msg}) for hide_file_names pattern: {pattern}').format(
|
||||||
msg=u(ex),
|
msg=u(ex),
|
||||||
pattern=u(pattern),
|
pattern=u(pattern),
|
||||||
))
|
))
|
||||||
|
|
|
@ -12,8 +12,9 @@
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import random
|
import random
|
||||||
|
import re
|
||||||
|
|
||||||
from .compat import open
|
from .compat import open, u
|
||||||
from .projects.git import Git
|
from .projects.git import Git
|
||||||
from .projects.mercurial import Mercurial
|
from .projects.mercurial import Mercurial
|
||||||
from .projects.projectfile import ProjectFile
|
from .projects.projectfile import ProjectFile
|
||||||
|
@ -65,9 +66,11 @@ def get_project_info(configs, heartbeat, data):
|
||||||
branch_name = project.branch()
|
branch_name = project.branch()
|
||||||
break
|
break
|
||||||
|
|
||||||
if project_name is None and not data.get('hide_project_names'):
|
if project_name is None:
|
||||||
project_name = data.get('project') or heartbeat.args.project
|
project_name = data.get('project') or heartbeat.args.project
|
||||||
|
|
||||||
|
hide_project = should_obfuscate_project(heartbeat)
|
||||||
|
|
||||||
if project_name is None or branch_name is None:
|
if project_name is None or branch_name is None:
|
||||||
|
|
||||||
for plugin_cls in REV_CONTROL_PLUGINS:
|
for plugin_cls in REV_CONTROL_PLUGINS:
|
||||||
|
@ -79,7 +82,7 @@ def get_project_info(configs, heartbeat, data):
|
||||||
if project.process():
|
if project.process():
|
||||||
project_name = project_name or project.name()
|
project_name = project_name or project.name()
|
||||||
branch_name = branch_name or project.branch()
|
branch_name = branch_name or project.branch()
|
||||||
if data.get('hide_project_names'):
|
if hide_project:
|
||||||
branch_name = None
|
branch_name = None
|
||||||
project_name = generate_project_name()
|
project_name = generate_project_name()
|
||||||
project_file = os.path.join(project.folder(), '.wakatime-project')
|
project_file = os.path.join(project.folder(), '.wakatime-project')
|
||||||
|
@ -90,12 +93,27 @@ def get_project_info(configs, heartbeat, data):
|
||||||
project_name = None
|
project_name = None
|
||||||
break
|
break
|
||||||
|
|
||||||
if project_name is None:
|
if project_name is None and not hide_project:
|
||||||
project_name = data.get('alternate_project') or heartbeat.args.alternate_project
|
project_name = data.get('alternate_project') or heartbeat.args.alternate_project
|
||||||
|
|
||||||
return project_name, branch_name
|
return project_name, branch_name
|
||||||
|
|
||||||
|
|
||||||
|
def should_obfuscate_project(heartbeat):
|
||||||
|
"""Returns True if hide_project_names is true or the path matches one in
|
||||||
|
the list of obfuscated project paths."""
|
||||||
|
|
||||||
|
for pattern in heartbeat.args.hide_project_names:
|
||||||
|
try:
|
||||||
|
compiled = re.compile(pattern, re.IGNORECASE)
|
||||||
|
return compiled.search(heartbeat.entity)
|
||||||
|
except re.error as ex:
|
||||||
|
log.warning(u('Regex error ({msg}) for hide_project_names pattern: {pattern}').format(
|
||||||
|
msg=u(ex),
|
||||||
|
pattern=u(pattern),
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
def get_configs_for_plugin(plugin_name, configs):
|
def get_configs_for_plugin(plugin_name, configs):
|
||||||
if configs and configs.has_section(plugin_name):
|
if configs and configs.has_section(plugin_name):
|
||||||
return dict(configs.items(plugin_name))
|
return dict(configs.items(plugin_name))
|
||||||
|
|
Loading…
Reference in a new issue