3 # This command is a simple remote-helper, that is used both as a
 
   4 # testcase for the remote-helper functionality, and as an example to
 
   5 # show remote-helper authors one possible implementation.
 
   7 # This is a Git <-> Git importer/exporter, that simply uses git
 
   8 # fast-import and git fast-export to consume and produce fast-import
 
  11 # To understand better the way things work, one can activate debug
 
  12 # traces by setting (to any value) the environment variables
 
  13 # GIT_TRANSPORT_HELPER_DEBUG and GIT_DEBUG_TESTGIT, to see messages
 
  14 # from the transport-helper side, or from this example remote-helper.
 
  16 # hashlib is only available in python >= 2.5
 
  19     _digest = hashlib.sha1
 
  25 sys.path.insert(0, os.getenv("GITPYTHONLIB","."))
 
  27 from git_remote_helpers.util import die, debug, warn
 
  28 from git_remote_helpers.git.repo import GitRepo
 
  29 from git_remote_helpers.git.exporter import GitExporter
 
  30 from git_remote_helpers.git.importer import GitImporter
 
  31 from git_remote_helpers.git.non_local import NonLocalGit
 
  33 def get_repo(alias, url):
 
  34     """Returns a git repository object initialized for usage.
 
  42     hasher.update(repo.path)
 
  43     repo.hash = hasher.hexdigest()
 
  45     repo.get_base_path = lambda base: os.path.join(
 
  46         base, 'info', 'fast-import', repo.hash)
 
  48     prefix = 'refs/testgit/%s/' % alias
 
  49     debug("prefix: '%s'", prefix)
 
  51     repo.gitdir = os.environ["GIT_DIR"]
 
  55     repo.exporter = GitExporter(repo)
 
  56     repo.importer = GitImporter(repo)
 
  57     repo.non_local = NonLocalGit(repo)
 
  62 def local_repo(repo, path):
 
  63     """Returns a git repository object initalized for usage.
 
  68     local.non_local = None
 
  69     local.gitdir = repo.gitdir
 
  70     local.alias = repo.alias
 
  71     local.prefix = repo.prefix
 
  72     local.hash = repo.hash
 
  73     local.get_base_path = repo.get_base_path
 
  74     local.exporter = GitExporter(local)
 
  75     local.importer = GitImporter(local)
 
  80 def do_capabilities(repo, args):
 
  81     """Prints the supported capabilities.
 
  86     print "refspec refs/heads/*:%s*" % repo.prefix
 
  88     dirname = repo.get_base_path(repo.gitdir)
 
  90     if not os.path.exists(dirname):
 
  93     path = os.path.join(dirname, 'testgit.marks')
 
  95     print "*export-marks %s" % path
 
  96     if os.path.exists(path):
 
  97         print "*import-marks %s" % path
 
  99     print # end capabilities
 
 102 def do_list(repo, args):
 
 103     """Lists all known references.
 
 105     Bug: This will always set the remote head to master for non-local
 
 106     repositories, since we have no way of determining what the remote
 
 107     head is at clone time.
 
 110     for ref in repo.revs:
 
 111         debug("? refs/heads/%s", ref)
 
 112         print "? refs/heads/%s" % ref
 
 115         debug("@refs/heads/%s HEAD" % repo.head)
 
 116         print "@refs/heads/%s HEAD" % repo.head
 
 118         debug("@refs/heads/master HEAD")
 
 119         print "@refs/heads/master HEAD"
 
 124 def update_local_repo(repo):
 
 125     """Updates (or clones) a local repo.
 
 131     path = repo.non_local.clone(repo.gitdir)
 
 132     repo.non_local.update(repo.gitdir)
 
 133     repo = local_repo(repo, path)
 
 137 def do_import(repo, args):
 
 138     """Exports a fast-import stream from testgit for git to import.
 
 142         die("Import needs exactly one ref")
 
 145         die("Need gitdir to import")
 
 151         line = sys.stdin.readline()
 
 154         if not line.startswith('import '):
 
 155             die("Expected import line.")
 
 157         # strip of leading 'import '
 
 158         ref = line[7:].strip()
 
 161     repo = update_local_repo(repo)
 
 162     repo.exporter.export_repo(repo.gitdir, refs)
 
 167 def do_export(repo, args):
 
 168     """Imports a fast-import stream from git to testgit.
 
 172         die("Need gitdir to export")
 
 174     update_local_repo(repo)
 
 175     changed = repo.importer.do_import(repo.gitdir)
 
 178         repo.non_local.push(repo.gitdir)
 
 186     'capabilities': do_capabilities,
 
 194     """Cleans up the url.
 
 197     if value.startswith('testgit::'):
 
 203 def read_one_line(repo):
 
 204     """Reads and processes one command.
 
 207     line = sys.stdin.readline()
 
 212         warn("Unexpected EOF")
 
 215     cmdline = cmdline.strip().split()
 
 217         # Blank line means we're about to quit
 
 221     debug("Got command '%s' with args '%s'", cmd, ' '.join(cmdline))
 
 223     if cmd not in COMMANDS:
 
 224         die("Unknown command, %s", cmd)
 
 234     """Starts a new remote helper for the specified repository.
 
 238         die("Expecting exactly three arguments.")
 
 241     if os.getenv("GIT_DEBUG_TESTGIT"):
 
 242         import git_remote_helpers.util
 
 243         git_remote_helpers.util.DEBUG = True
 
 245     alias = sanitize(args[1])
 
 246     url = sanitize(args[2])
 
 248     if not alias.isalnum():
 
 249         warn("non-alnum alias '%s'", alias)
 
 255     repo = get_repo(alias, url)
 
 257     debug("Got arguments %s", args[1:])
 
 262         more = read_one_line(repo)
 
 264 if __name__ == '__main__':
 
 265     sys.exit(main(sys.argv))