Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 77 additions & 1 deletion project_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
import re
import copy


from .json_file import JsonFile

SETTINGS_FILENAME = 'project_manager.sublime-settings'
REPODIRS = ('.git', '.svn', '.hg')
pm_settings = None


Expand Down Expand Up @@ -135,6 +135,31 @@ def f(*args, **kwargs):
return f


def find_repos(basedir, max_level=1, ignores=None):
""" os.walk with max depth. https://stackoverflow.com/a/234329 """
ignores = [i.lower() for i in (ignores or [])]
basedir = basedir.rstrip(os.path.sep)
assert os.path.isdir(basedir)
num_sep = basedir.count(os.path.sep)
for root, dirs, files in os.walk(basedir):
for dirname in dirs:
if not _is_ignored(root, ignores) and dirname in REPODIRS:
yield root, dirname
# yield root, dirs, files
num_sep_this = root.count(os.path.sep)
if num_sep + max_level <= num_sep_this:
del dirs[:]


def _is_ignored(dirname, ignores):
parts = dirname.split(os.path.sep)
for ignore in ignores:
for part in parts:
if ignore == part.lower():
return True
return False


class ProjectsInfo:
_instance = None

Expand Down Expand Up @@ -205,6 +230,7 @@ def refresh_projects(self):
raise Exception("Directory \"{}\" does not exists.".format(self._primary_dir))

self._info = self._get_all_projects_info()
self._auto_discover_repos()

def _get_all_projects_info(self):
all_projects_info = {}
Expand Down Expand Up @@ -265,6 +291,56 @@ def _load_sublime_project_files(self, folder):
os.rmdir(d)
return pfiles

def _auto_discover_repos(self):
try:
user_discover_dirs = pm_settings.get('auto_discover_base_directories')

# Get a list of discover_dirs to search for projects
node = computer_name()
if isinstance(user_discover_dirs, dict):
if node in user_discover_dirs:
user_discover_dirs = user_discover_dirs[node]
else:
user_discover_dirs = []
if isinstance(user_discover_dirs, str):
user_discover_dirs = [user_discover_dirs]

discover_dirs = []
for folder in user_discover_dirs:
p = expand_path(folder)
p = p.replace("$hostname", node)
discover_dirs.append(p)

# Convert existing project info to dict for easy lookup
existing = {info['folder']:key for key,info in self._info.items()}

# Find new repo directories
max_depth = pm_settings.get('auto_discover_max_recursion_depth', 1)
ignores = pm_settings.get('auto_discover_ignored_folders', [])
for basedir in discover_dirs:
if not os.path.isdir(basedir):
print('ProjectManager: {} is not a valid path'.format(basedir))
for folder, repodir in find_repos(basedir, max_depth, ignores):
if folder not in existing:
project_name = os.path.basename(folder)
self._create_new_project(project_name, folder)
except Exception as err:
print(err)

def _create_new_project(self, project_name, folder):
data = {"folders": [{
"binary_file_patterns": [],
"file_exclude_patterns": [],
"folder_exclude_patterns": [],
"name": project_name,
"path": folder,
}]}

filename = '{}.sublime-project'.format(project_name)
filepath = os.path.join(self.primary_dir(), filename)
print('ProjectManager: Creating {} -> {}'.format(filename, folder))
JsonFile(filepath).save(data)


class Manager:
def __init__(self, window):
Expand Down
22 changes: 21 additions & 1 deletion project_manager.sublime-settings
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,25 @@
// How the projects in the project list should be formatted. Supported variables
// are "project_name" and "active_project_indicator". For inactive projects
// "active_project_indicator" will be an empty string.
"project_display_format": "{project_name}{active_project_indicator}"
"project_display_format": "{project_name}{active_project_indicator}",

// Auto Discover Projects
// Any folders listed auto_discover_base_directories will be recursively
// searched for git, hg, or svn projects and a new .sublime-project will
// be created if one does not already exist. Format for this value is
// similar to projects above anc can be a string, list of strings or a
// dict containing {"hostname": ["path"]}. The variable `$hostname`
// will expand to the computer name in any paths.
"auto_discover_base_directories": {},

// Folder names to ignore when searching for projects.
"auto_discover_ignored_folders": [
"node_modules",
"out",
"typings",
"test"
],

// Max depth to recurse when searching for projects.
"auto_discover_max_recursion_depth": 2
}