b4a901ea65186c14830cc374fba84ccda6a9c0d9
[yap.git] / plugins / workdir.py
blobb4a901ea65186c14830cc374fba84ccda6a9c0d9
2 from yap.yap import YapCore, YapError
3 from yap.util import get_output, takes_options, run_safely
5 import os
6 import tempfile
8 class WorkdirPlugin(YapCore):
9 "Create extra work directories of a repository"
11 def __init__(self, *args, **flags):
12 super(WorkdirPlugin, self).__init__(*args, **flags)
14 def _unlock_branch(self, branch):
15 repo = get_output('git rev-parse --git-dir')[0]
16 dir = os.path.join(repo, 'yap', 'lock')
17 lockfile = os.path.join(dir, branch.replace('/', '\/'))
19 try:
20 os.unlink(lockfile)
21 except OSError:
22 pass
24 def _lock_branch(self, branch, locked_by):
25 repo = get_output('git rev-parse --git-dir')[0]
26 dir = os.path.join(repo, 'yap', 'lock')
27 try:
28 os.mkdir(dir)
29 except OSError:
30 pass
32 fd, tmplock = tempfile.mkstemp("yap")
33 os.write(fd, locked_by)
34 os.close(fd)
35 while True:
36 lockfile = os.path.join(dir, branch.replace('/', '\/'))
37 try:
38 os.link(tmplock, lockfile)
39 break
40 except OSError:
41 fd = file(lockfile)
42 user = fd.readline()
43 # If the workdir has been deleted, break his lock
44 if os.access(user, os.R_OK):
45 raise YapError("That branch is being used by an existing workdir")
46 os.unlink(lockfile)
47 continue
49 def cmd_workdir(self, branch, workdir=None):
50 self._check_git()
52 branches = get_output("git for-each-ref --format='%(refname)' 'refs/heads'")
53 if 'refs/heads/%s' % branch not in branches:
54 raise YapError("Not a branch: %s" % branch)
56 current = get_output("git symbolic-ref HEAD")[0]
58 repo = get_output('git rev-parse --git-dir')[0]
59 repo = os.path.join(os.getcwd(), repo)
60 repodir = os.path.dirname(repo)
61 if workdir is None:
62 repoparent, reponame = os.path.split(repodir)
63 workdir = os.path.join(repoparent, "%s-%s" % (reponame, branch))
65 # Make sure the current branch is locked
66 try:
67 self._lock_branch(current.replace('refs/heads/', ''), repodir)
68 except:
69 pass
71 self._lock_branch(branch, workdir)
73 try:
74 os.mkdir(workdir)
75 except OSError, e:
76 raise YapError("Can't create new workdir: %s (%s)" % (workdir, e))
78 os.chdir(workdir)
79 os.mkdir(".git")
80 os.chdir(".git")
82 for x in ["config", "refs", "logs/refs", "objects", "info",
83 "hooks", "packed-refs", "remotes", "svn"]:
84 if os.path.dirname(x):
85 os.makedirs(os.path.dirname(x))
86 os.symlink(os.path.join(repo, x), x)
88 run_safely("cp %s HEAD" % os.path.join(repo, 'HEAD'))
89 os.chdir("..")
90 run_safely("git symbolic-ref HEAD refs/heads/%s" % branch)
91 self.cmd_revert(**{'-a': 1})
93 def cmd_switch(self, branch, *args, **flags):
94 self._check_git()
96 current = get_output("git symbolic-ref HEAD")[0]
98 repo = get_output('git rev-parse --git-dir')[0]
99 self._lock_branch(branch, repo)
101 try:
102 super(WorkdirPlugin, self).cmd_switch(branch, *args, **flags)
103 except:
104 self._unlock_branch(branch)
105 raise
107 self._unlock_branch(current.replace('refs/heads/', ''))