Skip to content

Instantly share code, notes, and snippets.

@bollwyvl
Created March 18, 2012 18:59
Show Gist options
  • Save bollwyvl/2079831 to your computer and use it in GitHub Desktop.
Save bollwyvl/2079831 to your computer and use it in GitHub Desktop.
Rug stuff
class RugWorkspaceImplementation(WorkspaceImplementation):
def pretty_status(self, project=None):
"""
returns a nicely-formatted version of the rug status command
TODO: refactor when the pretty status comes out for reals
"""
if project is None:
project = self.repo._impl._rug
stat = project.status(porcelain=True)
if not stat.strip():
return {}
result = {}
for bits in stat.split("\n"):
bits = bits.split("\t")
result[bits[1]] = dict(
status=bits[0],
repo=bits[2],
)
return result
def stage(self, action, paths):
"""
Modifies files in the current commit.
If executed within the WSGI loop, this WILL explode.
TODO: this is the kind of thing we'll have to do.
"""
self.set_repo_status("staging")
try:
paths = [p
for p
in paths
if self.safe_path(p)]
self._stage_project(
self.repo._impl._rug,
action,
paths,
self.repo._impl._rug.dir)
except:
self.set_repo_status()
raise
self.set_repo_status()
def _stage_project(self, project, action, paths, root):
"""
Recursively stage the repos that are rquired for the given paths
"""
stat = self.pretty_status(project)
if not stat:
return
DELETED = self.stat_type_reverse[self.DELETED]
subproj_paths = {}
if action == WS.STAGE_STAGE:
for path in paths:
# this should give us the project-relative path
path = os.path.relpath(
os.path.join(root, path),
project.dir
)
if path in stat:
r = project.repos[stat[path]["repo"]]
if r["vcs"] == "rug":
subproj_paths[r["repo"]].setdefault([]).append(path)
else:
# this should give us the repo-relative path
proj_path = os.path.relpath(
os.path.join(root, path),
os.path.join(project.dir, r["path"])
)
log.info([
"ADD/REMOVE?",
root,
project.dir,
r["path"],
path,
proj_path])
if DELETED in stat[path]["status"]:
r['repo'].remove(proj_path)
else:
r['repo'].add(proj_path)
else:
raise NotImplementedError(
"%s does not belong to any known repo" % path)
# RECURSE
[self._stage(sp, sp_paths, root)
for sp, sp_paths in subproj_paths.items()]
def finish_commit(self, summary, message, paths=[]):
self.set_repo_status("committing")
try:
# a dict, passed around in recursion, that contains full fs paths
# to the repos that need committing
to_commit = {}
self._repos_to_commit(
self.repo._impl._rug,
paths,
to_commit,
self.repo._impl._rug.dir)
message = "\n".join([t or "" for t in [summary, message]]).strip()
# walk back through the repos, committing the leaves first
# and finally committing the highest project... NEEDS ADD?
for repo_path in sorted(to_commit.keys(), reverse=True):
to_commit[repo_path].commit(message)
except:
self.set_repo_status()
raise
self.set_repo_status()
def _repos_to_commit(self, project, paths, to_commit, root):
"""
Recursively collect the repos that need to be committed
given a set of paths
"""
stat = self.pretty_status(project)
if not stat:
return
pp = project.dir
subproj_paths = {}
for path in paths:
# get the project-relative path
path = os.path.relpath(
os.path.join(root, path),
project.dir
)
if path in stat:
r = project.repos[stat[path]['repo']]
if r['vcs'] == "rug":
subproj_paths[r['repo']].setdefault([]).append(path)
else:
# this duplicates stuff... meh
to_commit[os.path.join(pp, r['path'])] = r['repo']
# assuming commit is good enough for a project?
to_commit[pp] = project
else:
raise NotImplementedError(
"%s does not belong to any known repo" % path)
# RECURSE
[self._repos_to_commit(sp, sp_paths, to_commit, root)
for sp, sp_paths in subproj_paths.items()]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment