summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn O. Pearce <sop@google.com>2010-10-08 10:02:09 +0200
committerShawn O. Pearce <sop@google.com>2010-10-29 12:08:50 -0700
commit88443387b1b0508f43b57e104821c6b375806fea (patch)
treed3d1e5a3e6caecd8eabbdf7a1491ddcc2788aa3d
parent99482ae58a74e236fb40b65c267163a5690f39e1 (diff)
downloadgit-repo-88443387b1b0508f43b57e104821c6b375806fea.tar.gz
sync: Enable use of git clone --reference
Use git clone to initialize a new repository, and when possible allow callers to use --reference to reuse an existing checkout as the initial object storage area for the new checkout. Change-Id: Ie27f760247f311ce484c6d3e85a90d94da2febfc Signed-off-by: Shawn O. Pearce <sop@google.com>
-rw-r--r--project.py101
-rwxr-xr-xrepo5
-rw-r--r--subcmds/init.py14
3 files changed, 111 insertions, 9 deletions
diff --git a/project.py b/project.py
index 1b5d9a67..8ffed842 100644
--- a/project.py
+++ b/project.py
@@ -622,13 +622,14 @@ class Project(object):
622 """Perform only the network IO portion of the sync process. 622 """Perform only the network IO portion of the sync process.
623 Local working directory/branch state is not affected. 623 Local working directory/branch state is not affected.
624 """ 624 """
625 if not self.Exists: 625 is_new = not self.Exists
626 if is_new:
626 print >>sys.stderr 627 print >>sys.stderr
627 print >>sys.stderr, 'Initializing project %s ...' % self.name 628 print >>sys.stderr, 'Initializing project %s ...' % self.name
628 self._InitGitDir() 629 self._InitGitDir()
629 630
630 self._InitRemote() 631 self._InitRemote()
631 if not self._RemoteFetch(): 632 if not self._RemoteFetch(initial = is_new):
632 return False 633 return False
633 634
634 #Check that the requested ref was found after fetch 635 #Check that the requested ref was found after fetch
@@ -1024,7 +1025,7 @@ class Project(object):
1024 1025
1025## Direct Git Commands ## 1026## Direct Git Commands ##
1026 1027
1027 def _RemoteFetch(self, name=None, tag=None): 1028 def _RemoteFetch(self, name=None, tag=None, initial=False):
1028 if not name: 1029 if not name:
1029 name = self.remote.name 1030 name = self.remote.name
1030 1031
@@ -1032,6 +1033,60 @@ class Project(object):
1032 if self.GetRemote(name).PreConnectFetch(): 1033 if self.GetRemote(name).PreConnectFetch():
1033 ssh_proxy = True 1034 ssh_proxy = True
1034 1035
1036 if initial:
1037 alt = os.path.join(self.gitdir, 'objects/info/alternates')
1038 try:
1039 fd = open(alt, 'rb')
1040 try:
1041 ref_dir = fd.readline()
1042 if ref_dir and ref_dir.endswith('\n'):
1043 ref_dir = ref_dir[:-1]
1044 finally:
1045 fd.close()
1046 except IOError, e:
1047 ref_dir = None
1048
1049 if ref_dir and 'objects' == os.path.basename(ref_dir):
1050 ref_dir = os.path.dirname(ref_dir)
1051 packed_refs = os.path.join(self.gitdir, 'packed-refs')
1052 remote = self.GetRemote(name)
1053
1054 all = self.bare_ref.all
1055 ids = set(all.values())
1056 tmp = set()
1057
1058 for r, id in GitRefs(ref_dir).all.iteritems():
1059 if r not in all:
1060 if r.startswith(R_TAGS) or remote.WritesTo(r):
1061 all[r] = id
1062 ids.add(id)
1063 continue
1064
1065 if id in ids:
1066 continue
1067
1068 r = 'refs/_alt/%s' % id
1069 all[r] = id
1070 ids.add(id)
1071 tmp.add(r)
1072
1073 ref_names = list(all.keys())
1074 ref_names.sort()
1075
1076 tmp_packed = ''
1077 old_packed = ''
1078
1079 for r in ref_names:
1080 line = '%s %s\n' % (all[r], r)
1081 tmp_packed += line
1082 if r not in tmp:
1083 old_packed += line
1084
1085 _lwrite(packed_refs, tmp_packed)
1086
1087 else:
1088 ref_dir = None
1089
1035 cmd = ['fetch'] 1090 cmd = ['fetch']
1036 if not self.worktree: 1091 if not self.worktree:
1037 cmd.append('--update-head-ok') 1092 cmd.append('--update-head-ok')
@@ -1039,10 +1094,21 @@ class Project(object):
1039 if tag is not None: 1094 if tag is not None:
1040 cmd.append('tag') 1095 cmd.append('tag')
1041 cmd.append(tag) 1096 cmd.append(tag)
1042 return GitCommand(self, 1097
1043 cmd, 1098 ok = GitCommand(self,
1044 bare = True, 1099 cmd,
1045 ssh_proxy = ssh_proxy).Wait() == 0 1100 bare = True,
1101 ssh_proxy = ssh_proxy).Wait() == 0
1102
1103 if initial:
1104 if ref_dir:
1105 if old_packed != '':
1106 _lwrite(packed_refs, old_packed)
1107 else:
1108 os.remove(packed_refs)
1109 self.bare_git.pack_refs('--all', '--prune')
1110
1111 return ok
1046 1112
1047 def _Checkout(self, rev, quiet=False): 1113 def _Checkout(self, rev, quiet=False):
1048 cmd = ['checkout'] 1114 cmd = ['checkout']
@@ -1080,6 +1146,27 @@ class Project(object):
1080 os.makedirs(self.gitdir) 1146 os.makedirs(self.gitdir)
1081 self.bare_git.init() 1147 self.bare_git.init()
1082 1148
1149 mp = self.manifest.manifestProject
1150 ref_dir = mp.config.GetString('repo.reference')
1151
1152 if ref_dir:
1153 mirror_git = os.path.join(ref_dir, self.name + '.git')
1154 repo_git = os.path.join(ref_dir, '.repo', 'projects',
1155 self.relpath + '.git')
1156
1157 if os.path.exists(mirror_git):
1158 ref_dir = mirror_git
1159
1160 elif os.path.exists(repo_git):
1161 ref_dir = repo_git
1162
1163 else:
1164 ref_dir = None
1165
1166 if ref_dir:
1167 _lwrite(os.path.join(self.gitdir, 'objects/info/alternates'),
1168 os.path.join(ref_dir, 'objects') + '\n')
1169
1083 if self.manifest.IsMirror: 1170 if self.manifest.IsMirror:
1084 self.config.SetString('core.bare', 'true') 1171 self.config.SetString('core.bare', 'true')
1085 else: 1172 else:
diff --git a/repo b/repo
index 13742559..bdc05c3b 100755
--- a/repo
+++ b/repo
@@ -28,7 +28,7 @@ if __name__ == '__main__':
28del magic 28del magic
29 29
30# increment this whenever we make important changes to this script 30# increment this whenever we make important changes to this script
31VERSION = (1, 8) 31VERSION = (1, 9)
32 32
33# increment this if the MAINTAINER_KEYS block is modified 33# increment this if the MAINTAINER_KEYS block is modified
34KEYRING_VERSION = (1,0) 34KEYRING_VERSION = (1,0)
@@ -118,6 +118,9 @@ group.add_option('-m', '--manifest-name',
118group.add_option('--mirror', 118group.add_option('--mirror',
119 dest='mirror', action='store_true', 119 dest='mirror', action='store_true',
120 help='mirror the forrest') 120 help='mirror the forrest')
121group.add_option('--reference',
122 dest='reference',
123 help='location of mirror directory', metavar='DIR')
121 124
122# Tool 125# Tool
123group = init_optparse.add_option_group('repo Version options') 126group = init_optparse.add_option_group('repo Version options')
diff --git a/subcmds/init.py b/subcmds/init.py
index 4023ab6d..17edfa05 100644
--- a/subcmds/init.py
+++ b/subcmds/init.py
@@ -41,6 +41,13 @@ The optional -m argument can be used to specify an alternate manifest
41to be used. If no manifest is specified, the manifest default.xml 41to be used. If no manifest is specified, the manifest default.xml
42will be used. 42will be used.
43 43
44The --reference option can be used to point to a directory that
45has the content of a --mirror sync. This will make the working
46directory use as much data as possible from the local reference
47directory when fetching from the server. This will make the sync
48go a lot faster by reducing data traffic on the network.
49
50
44Switching Manifest Branches 51Switching Manifest Branches
45--------------------------- 52---------------------------
46 53
@@ -71,7 +78,9 @@ to update the working directory files.
71 g.add_option('--mirror', 78 g.add_option('--mirror',
72 dest='mirror', action='store_true', 79 dest='mirror', action='store_true',
73 help='mirror the forrest') 80 help='mirror the forrest')
74 81 g.add_option('--reference',
82 dest='reference',
83 help='location of mirror directory', metavar='DIR')
75 84
76 # Tool 85 # Tool
77 g = p.add_option_group('repo Version options') 86 g = p.add_option_group('repo Version options')
@@ -115,6 +124,9 @@ to update the working directory files.
115 r.ResetFetch() 124 r.ResetFetch()
116 r.Save() 125 r.Save()
117 126
127 if opt.reference:
128 m.config.SetString('repo.reference', opt.reference)
129
118 if opt.mirror: 130 if opt.mirror:
119 if is_new: 131 if is_new:
120 m.config.SetString('repo.mirror', 'true') 132 m.config.SetString('repo.mirror', 'true')