2013-07-08 01:38:01 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
|
|
wakatime.project
|
|
|
|
~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
Returns a project for the given file.
|
|
|
|
|
|
|
|
:copyright: (c) 2013 Alan Hamlett.
|
|
|
|
:license: BSD, see LICENSE for more details.
|
|
|
|
"""
|
|
|
|
|
2018-09-21 05:29:34 +00:00
|
|
|
import os
|
2013-07-08 01:38:01 +00:00
|
|
|
import logging
|
2018-09-21 05:29:34 +00:00
|
|
|
import random
|
2013-07-08 01:38:01 +00:00
|
|
|
|
2018-09-21 05:29:34 +00:00
|
|
|
from .compat import open
|
2013-07-08 01:38:01 +00:00
|
|
|
from .projects.git import Git
|
|
|
|
from .projects.mercurial import Mercurial
|
2017-11-06 03:51:43 +00:00
|
|
|
from .projects.projectfile import ProjectFile
|
2013-12-13 14:35:49 +00:00
|
|
|
from .projects.projectmap import ProjectMap
|
2013-07-08 01:38:01 +00:00
|
|
|
from .projects.subversion import Subversion
|
|
|
|
|
|
|
|
|
2014-07-25 08:01:39 +00:00
|
|
|
log = logging.getLogger('WakaTime')
|
2013-07-08 01:38:01 +00:00
|
|
|
|
2013-12-13 14:35:49 +00:00
|
|
|
|
|
|
|
# List of plugin classes to find a project for the current file path.
|
2015-06-30 02:47:04 +00:00
|
|
|
CONFIG_PLUGINS = [
|
2017-11-06 03:51:43 +00:00
|
|
|
ProjectFile,
|
2013-12-13 14:35:49 +00:00
|
|
|
ProjectMap,
|
2015-06-30 02:47:04 +00:00
|
|
|
]
|
|
|
|
REV_CONTROL_PLUGINS = [
|
2013-07-08 01:38:01 +00:00
|
|
|
Git,
|
|
|
|
Mercurial,
|
|
|
|
Subversion,
|
|
|
|
]
|
|
|
|
|
|
|
|
|
2017-11-09 07:12:05 +00:00
|
|
|
def get_project_info(configs, heartbeat, data):
|
2015-06-30 02:47:04 +00:00
|
|
|
"""Find the current project and branch.
|
|
|
|
|
|
|
|
First looks for a .wakatime-project file. Second, uses the --project arg.
|
|
|
|
Third, uses the folder name from a revision control repository. Last, uses
|
|
|
|
the --alternate-project arg.
|
|
|
|
|
|
|
|
Returns a project, branch tuple.
|
|
|
|
"""
|
|
|
|
|
2017-11-09 07:12:05 +00:00
|
|
|
project_name, branch_name = heartbeat.project, heartbeat.branch
|
2015-06-30 02:47:04 +00:00
|
|
|
|
2017-11-09 07:12:05 +00:00
|
|
|
if heartbeat.type != 'file':
|
|
|
|
project_name = project_name or heartbeat.args.project or heartbeat.args.alternate_project
|
|
|
|
return project_name, branch_name
|
2015-06-30 02:47:04 +00:00
|
|
|
|
2017-11-09 07:12:05 +00:00
|
|
|
if project_name is None or branch_name is None:
|
|
|
|
|
|
|
|
for plugin_cls in CONFIG_PLUGINS:
|
|
|
|
|
|
|
|
plugin_name = plugin_cls.__name__.lower()
|
|
|
|
plugin_configs = get_configs_for_plugin(plugin_name, configs)
|
2015-06-30 02:47:04 +00:00
|
|
|
|
2017-11-09 07:12:05 +00:00
|
|
|
project = plugin_cls(heartbeat.entity, configs=plugin_configs)
|
|
|
|
if project.process():
|
|
|
|
project_name = project_name or project.name()
|
|
|
|
branch_name = project.branch()
|
|
|
|
break
|
2015-06-30 02:47:04 +00:00
|
|
|
|
|
|
|
if project_name is None:
|
2017-11-09 07:12:05 +00:00
|
|
|
project_name = data.get('project') or heartbeat.args.project
|
2015-06-30 02:47:04 +00:00
|
|
|
|
2018-09-21 05:29:34 +00:00
|
|
|
hide_project = heartbeat.should_obfuscate_project()
|
2019-03-31 01:53:40 +00:00
|
|
|
if hide_project and project_name is not None:
|
|
|
|
return project_name, None
|
2018-09-21 05:29:34 +00:00
|
|
|
|
2015-06-30 02:47:04 +00:00
|
|
|
if project_name is None or branch_name is None:
|
|
|
|
|
|
|
|
for plugin_cls in REV_CONTROL_PLUGINS:
|
|
|
|
|
|
|
|
plugin_name = plugin_cls.__name__.lower()
|
|
|
|
plugin_configs = get_configs_for_plugin(plugin_name, configs)
|
|
|
|
|
2017-11-09 07:12:05 +00:00
|
|
|
project = plugin_cls(heartbeat.entity, configs=plugin_configs)
|
2015-06-30 02:47:04 +00:00
|
|
|
if project.process():
|
|
|
|
project_name = project_name or project.name()
|
|
|
|
branch_name = branch_name or project.branch()
|
2018-09-21 05:29:34 +00:00
|
|
|
if hide_project:
|
|
|
|
branch_name = None
|
|
|
|
project_name = generate_project_name()
|
|
|
|
project_file = os.path.join(project.folder(), '.wakatime-project')
|
|
|
|
try:
|
|
|
|
with open(project_file, 'w') as fh:
|
|
|
|
fh.write(project_name)
|
|
|
|
except IOError:
|
|
|
|
project_name = None
|
2015-06-30 02:47:04 +00:00
|
|
|
break
|
|
|
|
|
2018-09-21 05:29:34 +00:00
|
|
|
if project_name is None and not hide_project:
|
2017-11-09 07:12:05 +00:00
|
|
|
project_name = data.get('alternate_project') or heartbeat.args.alternate_project
|
2015-06-30 02:47:04 +00:00
|
|
|
|
|
|
|
return project_name, branch_name
|
|
|
|
|
|
|
|
|
|
|
|
def get_configs_for_plugin(plugin_name, configs):
|
|
|
|
if configs and configs.has_section(plugin_name):
|
|
|
|
return dict(configs.items(plugin_name))
|
2013-07-21 17:44:23 +00:00
|
|
|
return None
|
2018-09-21 05:29:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
def generate_project_name():
|
|
|
|
"""Generates a random project name."""
|
|
|
|
|
|
|
|
adjectives = [
|
|
|
|
'aged', 'ancient', 'autumn', 'billowing', 'bitter', 'black', 'blue', 'bold',
|
|
|
|
'broad', 'broken', 'calm', 'cold', 'cool', 'crimson', 'curly', 'damp',
|
|
|
|
'dark', 'dawn', 'delicate', 'divine', 'dry', 'empty', 'falling', 'fancy',
|
|
|
|
'flat', 'floral', 'fragrant', 'frosty', 'gentle', 'green', 'hidden', 'holy',
|
|
|
|
'icy', 'jolly', 'late', 'lingering', 'little', 'lively', 'long', 'lucky',
|
|
|
|
'misty', 'morning', 'muddy', 'mute', 'nameless', 'noisy', 'odd', 'old',
|
|
|
|
'orange', 'patient', 'plain', 'polished', 'proud', 'purple', 'quiet', 'rapid',
|
|
|
|
'raspy', 'red', 'restless', 'rough', 'round', 'royal', 'shiny', 'shrill',
|
|
|
|
'shy', 'silent', 'small', 'snowy', 'soft', 'solitary', 'sparkling', 'spring',
|
|
|
|
'square', 'steep', 'still', 'summer', 'super', 'sweet', 'throbbing', 'tight',
|
|
|
|
'tiny', 'twilight', 'wandering', 'weathered', 'white', 'wild', 'winter', 'wispy',
|
|
|
|
'withered', 'yellow', 'young'
|
|
|
|
]
|
|
|
|
nouns = [
|
|
|
|
'art', 'band', 'bar', 'base', 'bird', 'block', 'boat', 'bonus',
|
|
|
|
'bread', 'breeze', 'brook', 'bush', 'butterfly', 'cake', 'cell', 'cherry',
|
|
|
|
'cloud', 'credit', 'darkness', 'dawn', 'dew', 'disk', 'dream', 'dust',
|
|
|
|
'feather', 'field', 'fire', 'firefly', 'flower', 'fog', 'forest', 'frog',
|
|
|
|
'frost', 'glade', 'glitter', 'grass', 'hall', 'hat', 'haze', 'heart',
|
|
|
|
'hill', 'king', 'lab', 'lake', 'leaf', 'limit', 'math', 'meadow',
|
|
|
|
'mode', 'moon', 'morning', 'mountain', 'mouse', 'mud', 'night', 'paper',
|
|
|
|
'pine', 'poetry', 'pond', 'queen', 'rain', 'recipe', 'resonance', 'rice',
|
|
|
|
'river', 'salad', 'scene', 'sea', 'shadow', 'shape', 'silence', 'sky',
|
|
|
|
'smoke', 'snow', 'snowflake', 'sound', 'star', 'sun', 'sun', 'sunset',
|
|
|
|
'surf', 'term', 'thunder', 'tooth', 'tree', 'truth', 'union', 'unit',
|
|
|
|
'violet', 'voice', 'water', 'waterfall', 'wave', 'wildflower', 'wind', 'wood'
|
|
|
|
]
|
|
|
|
numbers = [str(x) for x in range(10)]
|
|
|
|
return ' '.join([
|
|
|
|
random.choice(adjectives).capitalize(),
|
|
|
|
random.choice(nouns).capitalize(),
|
|
|
|
random.choice(numbers) + random.choice(numbers),
|
|
|
|
])
|