Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add indirect branch tracking

  • Loading branch information...
commit 8ad4d51ed0cc38cdbda0f4574a3efb83c48f69df 1 parent 5e27618
@toddlipcon toddlipcon authored
Showing with 199 additions and 8 deletions.
  1. +62 −3 crepo.py
  2. +68 −5 manifest.py
  3. +69 −0 shell-tests/follow_indirect.sh
View
65 crepo.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python2.5
# (c) Copyright 2009 Cloudera, Inc.
-
+from __future__ import with_statement
+from contextlib import closing
import os
import sys
import optparse
@@ -317,8 +318,65 @@ def dump_refs(args):
"origin/" + repo.current_branch(),
indent=2)
check_dirty_repo(repo, indent=2)
-
+def update_indirect(args):
+ """
+ Change track-indirect projects to point to what you've got them pointed at.
+ """
+ man = load_manifest()
+
+
+ # parse args
+ force = False
+ for arg in args:
+ if arg == "-f":
+ force = True
+
+ # Some markers so we can output status at the end
+ saw_indirects = False # are there any indirect tracks?
+ possible_actions = False # were there any where we could take action?
+
+ # Come up with the list of indirect projects we might want to twiddle
+ for project in man.projects.itervalues():
+ if not isinstance(project.tracker, manifest.TrackIndirect):
+ continue
+ saw_indirects = True
+ repo = project.git_repo
+ tracker = project.tracker
+ (left, right) = project.tracking_status
+
+ # If we're pointed at what we're supposed to, skip
+ if left == 0 and right == 0:
+ continue
+
+ possible_actions = True
+ print "Project %s:" % project.name
+ print " Indirect file: %s" % tracker.indirection_file
+ print
+ project_status(project, indent=2)
+
+ cur_revision = repo.rev_parse("HEAD")
+
+ # We are strictly ahead of where we should be
+ if left > 0 and right == 0:
+ if not force:
+ print
+ print "Do you want to update this project to the currently checked out revision?"
+ print " (revision %s)" % cur_revision
+ print " (Y/n): ",
+ sys.stdout.flush()
+ res = sys.stdin.readline().rstrip().lower()
+ if res != 'y' and res != '':
+ continue
+
+ with closing(file(tracker.indirection_file, "w")) as f:
+ print >>f, cur_revision
+ print "Updated"
+
+ if not saw_indirects:
+ print "No indirect projects!"
+ elif not possible_actions:
+ print "All indirect projects are up to date!"
COMMANDS = {
'help': help,
@@ -332,7 +390,8 @@ def dump_refs(args):
'status': status,
'check-dirty': check_dirty,
'setup-remotes': ensure_remotes,
- 'dump-refs': dump_refs
+ 'dump-refs': dump_refs,
+ 'update-indirect': update_indirect,
}
def usage():
View
73 manifest.py
@@ -1,5 +1,8 @@
#!/usr/bin/env python2.5
# (c) Copyright 2009 Cloudera, Inc.
+from __future__ import with_statement
+
+from contextlib import closing
import logging
import os
import simplejson
@@ -52,6 +55,41 @@ def add_project(self, project):
self.projects[project.name] = project
+class IndirectionDb(object):
+ # KILL ME?
+ OPEN_DBS = {}
+
+ def __init__(self, path):
+ self.path = path
+
+ for line in file(path).xreadlines():
+ line = line.rstrip()
+ key, val = line.split('=', 1)
+ self.data[key] = val
+
+ def dump_to(self, path):
+ with closing(file(path, "w")) as f:
+ for key, val in sorted(self.data.iteritems()):
+ print >>f, "%s=%s\n" % (key, val)
+
+ def get_indirection(self, key):
+ return self.data.get(key)
+
+ def set_indirection(self, key, val):
+ self.data[key] = val
+
+ @classmethod
+ def load(cls, path):
+ path = os.path.abspath(path)
+ if path in cls.OPEN_DBS:
+ return cls.OPEN_DBS[path]
+ else:
+ db = IndirectionDb(path)
+ cls.OPEN_DBS[path] = db
+ return db
+
+
+
class Remote(object):
def __init__(self,
fetch):
@@ -99,6 +137,7 @@ def tracking_status(self, repo):
def create_tracking_branch(self, repo):
repo.command(["branch", "crepo", self.hash])
+
class TrackTag(object):
def __init__(self, tag):
self.tag = tag
@@ -119,6 +158,27 @@ def create_tracking_branch(self, repo):
repo.command(["branch", self.tag, self.remote_ref])
+class TrackIndirect(object):
+ def __init__(self, indirection_file):
+ self.indirection_file = os.path.abspath(indirection_file)
+
+ @property
+ def tracking_branch(self):
+ return "crepo"
+
+ @property
+ def remote_ref(self):
+ return file(self.indirection_file).read().strip()
+
+ def tracking_status(self, repo):
+ return repo.tracking_status(
+ self.tracking_branch, self.remote_ref)
+
+ def create_tracking_branch(self, repo):
+ repo.command(["branch", self.tracking_branch, self.remote_ref])
+
+
+
class Project(object):
def __init__(self,
name=None,
@@ -159,31 +219,34 @@ def from_dict(manifest, name, data):
track_tag = data.get('track-tag')
track_branch = data.get('track-branch')
track_hash = data.get('track-hash')
+ track_indirect = data.get('track-indirect')
- if len(filter(None, [track_tag, track_branch, track_hash])) > 1:
+ if len(filter(None, [track_tag, track_branch, track_hash, track_indirect])) > 1:
raise Exception(
"Cannot specify more than one of track-branch, track-tag, " +
- "or track-hash for project %s" % name)
+ "track-hash, or track-indirect for project %s" % name)
# This is old and deprecated
ref = data.get('refspec')
- if not track_tag and not track_branch and not track_hash:
+ if not track_tag and not track_branch and not track_hash and not track_indirect:
if ref:
logging.warn("'ref' is deprecated - use either track-branch or track-tag " +
"for project %s" % name)
track_branch = ref
else:
track_branch = "master"
-
+
if track_tag:
tracker = TrackTag(track_tag)
elif track_branch:
tracker = TrackBranch(from_remote, track_branch)
elif track_hash:
tracker = TrackHash(track_hash)
+ elif track_indirect:
+ tracker = TrackIndirect(track_indirect)
else:
assert False and "Cannot get here!"
-
+
return Project(name=name,
manifest=manifest,
View
69 shell-tests/follow_indirect.sh
@@ -0,0 +1,69 @@
+#!/bin/bash -x
+
+set -e
+
+BINDIR=$(readlink -f $(dirname $0))
+CREPO=$BINDIR/../crepo.py
+
+TESTDIR=${TESTDIR:-/tmp/follow_indirect.$$}
+mkdir -p $TESTDIR
+cd $TESTDIR
+
+
+################
+# REPO A
+################
+mkdir repo_a
+pushd repo_a
+git init
+echo "First commit" > file_a
+git add . && git commit -a -m '1'
+
+echo "Second commit" > file_b
+git add . && git commit -a -m '2'
+git tag commit_b
+
+echo "Third commit" >> file_a
+git add . && git commit -a -m '3'
+COMMIT_C_HASH=$(git rev-parse HEAD)
+REPO_A=`pwd`
+
+popd
+
+##############
+# Run crepo in a new dir
+##############
+mkdir tests
+pushd tests
+
+cat > manifest.json <<EOF
+{
+ "remotes":
+ {"origin": { "fetch": "$TESTDIR/%(name)s" }},
+
+ "projects":
+ {"repo_a": { "track-indirect": ".crepo/repo_a" }}
+}
+EOF
+
+mkdir .crepo
+echo "commit_b" > .crepo/repo_a
+
+$CREPO sync
+
+## Check that the checkout is correct
+pushd repo_a
+test "$(git rev-parse HEAD)" == "$(git rev-parse refs/tags/commit_b)"
+test $(git remote) == "origin"
+test -f file_a
+popd
+
+# Now go check out the new guy
+pushd repo_a
+git reset --hard $COMMIT_C_HASH
+popd
+
+# And update the indirects
+$CREPO update-indirect -f
+
+test "$(cat .crepo/repo_a)" == "$COMMIT_C_HASH"
Please sign in to comment.
Something went wrong with that request. Please try again.