def cmd_svn(self, subcmd): "enable" if subcmd not in ["enable"]: raise TypeError if "svn" in [x[0] for x in self._list_remotes()]: raise YapError("A remote named 'svn' already exists") if not run_command("git config svn-remote.svn.branches"): raise YapError("Cannot currently enable in a repository with svn branches") url = get_output("git config svn-remote.svn.url") if not url: raise YapError("Not a git-svn repository?") fetch = get_output("git config svn-remote.svn.fetch") assert fetch lhs, rhs = fetch[0].split(':') rev = get_output("git rev-parse %s" % rhs) assert rev run_safely("git update-ref refs/remotes/svn/trunk %s" % rev[0]) url = '/'.join((url[0], lhs)) self._configure_repo(url) run_safely("git update-ref -d %s %s" % (rhs, rev[0]))
def _create_tagged_blob(self): keys = dict() for i in get_output("git config --list | grep ^svn-remote."): k, v = i.split('=') keys[k] = v blob = RepoBlob(keys) for b in get_output("git for-each-ref --format='%(refname)' 'refs/remotes/svn'"): b = b.replace('refs/remotes/svn/', '') blob.add_metadata(b) fd_w, fd_r = os.popen2("git hash-object -w --stdin") pickle.dump(blob, fd_w) fd_w.close() hash = fd_r.readline().strip() run_safely("git tag -f yap-svn %s" % hash)
def cmd_workdir(self, branch, workdir=None): "<branch> [workdir]" self._check_git() branches = get_output("git for-each-ref --format='%(refname)' 'refs/heads'") if 'refs/heads/%s' % branch not in branches: raise YapError("Not a branch: %s" % branch) current = get_output("git symbolic-ref HEAD")[0] repodir = self._get_repodir() repo = os.path.join(repodir, '.git') if workdir is None: repoparent, reponame = os.path.split(repodir) workdir = os.path.join(repoparent, "%s-%s" % (reponame, branch)) # Make sure the current branch is locked try: self._lock_branch(current.replace('refs/heads/', ''), repodir) except: pass self._lock_branch(branch, workdir) # If we fail after this point, unlock the branch try: try: os.mkdir(workdir) except OSError, e: raise YapError("Can't create new workdir: %s (%s)" % (workdir, e)) os.chdir(workdir) os.mkdir(".git") os.chdir(".git") for x in ["config", "refs", "logs/refs", "objects", "info", "hooks", "packed-refs", "remotes", "yap", "svn"]: if os.path.dirname(x): os.makedirs(os.path.dirname(x)) os.symlink(os.path.join(repo, x), x) run_safely("cp %s HEAD" % os.path.join(repo, 'HEAD')) os.chdir("..") run_safely("git symbolic-ref HEAD refs/heads/%s" % branch) self.cmd_revert(**{'-a': 1})
def _cleanup_branches(self): for b in get_output("git for-each-ref --format='%(refname)' 'refs/remotes/svn/*@*'"): head = b.replace('refs/remotes/svn/', '') path = os.path.join(".git", "svn", "svn", head) try: files = os.listdir(path) for f in files: os.unlink(os.path.join(path, f)) os.rmdir(path) except OSError: pass path = os.path.join(".git", "svn", "refs", "remotes", "svn", head) try: files = os.listdir(path) for f in files: os.unlink(os.path.join(path, f)) os.rmdir(path) except OSError: pass ref = get_output("git rev-parse %s" % b) if ref: run_safely("git update-ref -d %s %s" % (b, ref[0]))
def cmd_clone(self, *args, **flags): handled = True if not args: handled = False if (handled and not args[0].startswith("http") and not args[0].startswith("svn") and not args[0].startswith("file://")): handled = False if handled and run_command("svn info %s" % args[0]): handled = False if handled: self._clone_svn(*args, **flags) else: super(SvnPlugin, self).cmd_clone(*args, **flags) if self._enabled(): # nothing to do return run_safely("git fetch origin --tags") hash = get_output("git rev-parse --verify refs/tags/yap-svn 2>/dev/null") if not hash: return fd = os.popen("git cat-file blob %s" % hash[0]) blob = pickle.load(fd) for k, v in blob.keys.items(): run_safely("git config %s %s" % (k, v)) self.cmd_repo("svn", blob.keys['svn-remote.svn.url']) os.system("git config yap.svn.enabled 1") run_safely("git fetch origin 'refs/remotes/svn/*:refs/remotes/svn/*'") for b in blob.metadata.keys(): branch = os.path.join(".git", "svn", "svn", b) os.makedirs(branch) fd = file(os.path.join(branch, ".rev_map.%s" % blob.uuid), "w") rev, metadata = blob.metadata[b] fd.write(metadata) branch = os.path.join(".git", "svn", "refs", "remotes", "svn", b) os.makedirs(branch) fd = file(os.path.join(branch, ".rev_map.%s" % blob.uuid), "w") rev, metadata = blob.metadata[b] fd.write(metadata) run_command("git update-ref refs/remotes/svn/%s %s" % (b, rev))
def _push_svn(self, branch, **flags): if '-d' in flags: raise YapError("Deleting svn branches not supported") print "Verifying branch is up-to-date" run_safely("git svn fetch svn") branch = branch.replace('refs/heads/', '') rev = get_output("git rev-parse --verify refs/remotes/svn/%s" % branch) # Create the branch if requested if not rev: if '-c' not in flags: raise YapError("No matching branch on the repo. Use -c to create a new branch there.") src = get_output("git svn info | gawk '/URL:/{print $2}'")[0] brev = get_output("git svn info | gawk '/Revision:/{print $2}'")[0] root = get_output("git config svn-remote.svn.url")[0] branch_path = get_output("git config svn-remote.svn.branches")[0].split(':')[0] branch_path = branch_path.rstrip('/*') dst = '/'.join((root, branch_path, branch)) # Create the branch in svn run_safely("svn cp -r%s %s %s -m 'create branch %s'" % (brev, src, dst, branch)) run_safely("git svn fetch svn") rev = get_output("git rev-parse refs/remotes/svn/%s 2>/dev/null" % branch) base = get_output("git svn find-rev r%s" % brev) # Apply our commits to the new branch try: fd, tmpfile = tempfile.mkstemp("yap") os.close(fd) os.system("git format-patch -k --stdout '%s' > %s" % (base[0], tmpfile)) start = get_output("git rev-parse HEAD") self.cmd_point("refs/remotes/svn/%s" % branch, **{'-f': True}) stat = os.stat(tmpfile) size = stat[6] if size > 0: rc = run_command("git am -3 %s" % tmpfile) if (rc): self.cmd_point(start[0], **{'-f': True}) raise YapError("Failed to port changes to new svn branch") finally: os.unlink(tmpfile) base = get_output("git merge-base HEAD %s" % rev[0]) if base[0] != rev[0]: raise YapError("Branch not up-to-date. Update first.") current = get_output("git symbolic-ref HEAD") if not current: raise YapError("Not on a branch!") current = current[0].replace('refs/heads/', '') self._confirm_push(current, branch, "svn") if run_command("git update-index --refresh"): raise YapError("Can't push with uncommitted changes") master = get_output("git rev-parse --verify refs/heads/master 2>/dev/null") os.system("git svn dcommit") run_safely("git svn rebase") if not master: master = get_output("git rev-parse --verify refs/heads/master 2>/dev/null") if master: run_safely("git update-ref -d refs/heads/master %s" % master[0])