workdirs: ensure the .yap directory exists in the new repo
[yap.git] / plugins / workdir.py
blob7587b785edc8f38f6f9eb6775702938b33d3ad17
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 try:
18 os.makedirs(dir)
19 except OSError:
20 pass
22 lockfile = os.path.join(dir, branch.replace('/', '\/'))
24 try:
25 os.unlink(lockfile)
26 except OSError:
27 pass
29 def _lock_branch(self, branch, locked_by):
30 repo = get_output('git rev-parse --git-dir')[0]
31 dir = os.path.join(repo, 'yap', 'lock')
32 try:
33 os.makedirs(dir)
34 except OSError:
35 pass
37 fd, tmplock = tempfile.mkstemp("yap", dir=dir)
38 try:
39 os.write(fd, locked_by)
40 os.close(fd)
41 while True:
42 lockfile = os.path.join(dir, branch.replace('/', '\/'))
43 try:
44 os.link(tmplock, lockfile)
45 break
46 except OSError, e:
47 try:
48 fd = file(lockfile)
49 except:
50 raise e
51 user = fd.readline()
52 # If the workdir has been deleted, break his lock
53 if os.access(user, os.R_OK):
54 raise YapError("That branch is being used by an existing workdir")
55 os.unlink(lockfile)
56 continue
57 finally:
58 os.unlink(tmplock)
60 def _get_repodir(self):
61 repo = get_output('git rev-parse --git-dir')[0]
62 if not repo.startswith('/'):
63 repo = os.path.join(os.getcwd(), repo)
64 repodir = os.path.dirname(repo)
65 return repodir
67 def cmd_workdir(self, branch, workdir=None):
68 "<branch> [workdir]"
70 self._check_git()
72 branches = get_output("git for-each-ref --format='%(refname)' 'refs/heads'")
73 if 'refs/heads/%s' % branch not in branches:
74 raise YapError("Not a branch: %s" % branch)
76 current = get_output("git symbolic-ref HEAD")[0]
77 repodir = self._get_repodir()
78 repo = os.path.join(repodir, '.git')
79 if workdir is None:
80 repoparent, reponame = os.path.split(repodir)
81 workdir = os.path.join(repoparent, "%s-%s" % (reponame, branch))
83 # Make sure the current branch is locked
84 try:
85 self._lock_branch(current.replace('refs/heads/', ''), repodir)
86 except:
87 pass
89 self._lock_branch(branch, workdir)
91 try:
92 os.mkdir(workdir)
93 except OSError, e:
94 raise YapError("Can't create new workdir: %s (%s)" % (workdir, e))
96 os.chdir(workdir)
97 os.mkdir(".git")
98 os.chdir(".git")
100 for x in ["config", "refs", "logs/refs", "objects", "info",
101 "hooks", "packed-refs", "remotes", "yap", "svn"]:
102 if os.path.dirname(x):
103 os.makedirs(os.path.dirname(x))
104 os.symlink(os.path.join(repo, x), x)
106 run_safely("cp %s HEAD" % os.path.join(repo, 'HEAD'))
107 os.chdir("..")
108 run_safely("git symbolic-ref HEAD refs/heads/%s" % branch)
109 self.cmd_revert(**{'-a': 1})
111 print "Workdir created at %s for branch %s" % (workdir, branch)
113 def cmd_branch(self, *args, **flags):
114 if '-d' in flags:
115 branch = flags['-d']
116 repodir = self._get_repodir()
117 self._lock_branch(branch, repodir)
118 else:
119 branch = None
121 try:
122 super(WorkdirPlugin, self).cmd_branch(*args, **flags)
123 finally:
124 if branch:
125 self._unlock_branch(branch)
127 def cmd_switch(self, branch, *args, **flags):
128 self._check_git()
130 current = get_output("git symbolic-ref HEAD")[0]
132 repodir = self._get_repodir()
133 self._lock_branch(branch, repodir)
135 try:
136 super(WorkdirPlugin, self).cmd_switch(branch, *args, **flags)
137 except:
138 self._unlock_branch(branch)
139 raise
141 self._unlock_branch(current.replace('refs/heads/', ''))