Compare commits

...

4 Commits

Author SHA1 Message Date
9371979628 Revert "Implementation of manifest defined githooks"
This reverts commit 38e4387f8e.

A "repo init" followed by "repo sync" is meant to be as safe as
"git clone".  In particular it should not run arbitrary code provided
by the manifest owner.

It would still be nice to have support for manifest-defined git hooks
--- they'd just need a prompt like the upload RepoHook has.  Hopefully
a later change can bring them back.

Change-Id: I5ecd90fb5c2ed64f103d856d1ffcba38a47b062d
Signed-off-by: Jonathan Nieder <jrn@google.com>
2015-03-17 11:29:58 -07:00
2086004261 Merge "Don't exit with error on HTTP 401 when downloading clone bundle" 2015-03-11 17:25:45 +00:00
2338788050 Don't exit with error on HTTP 401 when downloading clone bundle
If the server returns HTTP 401 (unauthorized) when attempting to
download clone bundle files, ignore it and continue, rather than
exiting with a fatal error.

Change-Id: I2c7ee03e149c354c7e4ad6ea1ebf266534778fe1
2015-03-11 07:43:40 +00:00
0402cd882a Add space between project path and branch in repo status.
Currently, paths longer than 39 chars have no space after them so it looks
like this:

project path/branch master

Change-Id: I4c1bb13648ac099ade8a8d4ebafa04131571f842
2015-03-11 07:42:17 +00:00
5 changed files with 30 additions and 119 deletions

View File

@ -31,7 +31,7 @@ following DTD:
<!ELEMENT notice (#PCDATA)> <!ELEMENT notice (#PCDATA)>
<!ELEMENT remote (projecthook?)> <!ELEMENT remote (EMPTY)>
<!ATTLIST remote name ID #REQUIRED> <!ATTLIST remote name ID #REQUIRED>
<!ATTLIST remote alias CDATA #IMPLIED> <!ATTLIST remote alias CDATA #IMPLIED>
<!ATTLIST remote fetch CDATA #REQUIRED> <!ATTLIST remote fetch CDATA #REQUIRED>
@ -73,10 +73,6 @@ following DTD:
<!ATTLIST extend-project path CDATA #IMPLIED> <!ATTLIST extend-project path CDATA #IMPLIED>
<!ATTLIST extend-project groups CDATA #IMPLIED> <!ATTLIST extend-project groups CDATA #IMPLIED>
<!ELEMENT projecthook (EMPTY)>
<!ATTLIST projecthook name CDATA #REQUIRED>
<!ATTLIST projecthook revision CDATA #REQUIRED>
<!ELEMENT remove-project (EMPTY)> <!ELEMENT remove-project (EMPTY)>
<!ATTLIST remove-project name CDATA #REQUIRED> <!ATTLIST remove-project name CDATA #REQUIRED>
@ -310,15 +306,6 @@ target manifest to include - it must be a usable manifest on its own.
Attribute `name`: the manifest to include, specified relative to Attribute `name`: the manifest to include, specified relative to
the manifest repository's root. the manifest repository's root.
Element projecthook
-------------------
This element is used to define a per-remote hook git that is
fetched and applied to all projects using the remote. The project-
hook functionality allows for company/team .git/hooks to be used.
The hooks in the supplied project and revision are supplemented to
the current repo stock hooks for each project. Supplemented hooks
overrule any stock hooks.
Local Manifests Local Manifests
=============== ===============

View File

@ -64,9 +64,7 @@ class _XmlRemote(object):
fetch=None, fetch=None,
manifestUrl=None, manifestUrl=None,
review=None, review=None,
revision=None, revision=None):
projecthookName=None,
projecthookRevision=None):
self.name = name self.name = name
self.fetchUrl = fetch self.fetchUrl = fetch
self.manifestUrl = manifestUrl self.manifestUrl = manifestUrl
@ -74,8 +72,6 @@ class _XmlRemote(object):
self.reviewUrl = review self.reviewUrl = review
self.revision = revision self.revision = revision
self.resolvedFetchUrl = self._resolveFetchUrl() self.resolvedFetchUrl = self._resolveFetchUrl()
self.projecthookName = projecthookName
self.projecthookRevision = projecthookRevision
def __eq__(self, other): def __eq__(self, other):
return self.__dict__ == other.__dict__ return self.__dict__ == other.__dict__
@ -171,11 +167,6 @@ class XmlManifest(object):
e.setAttribute('review', r.reviewUrl) e.setAttribute('review', r.reviewUrl)
if r.revision is not None: if r.revision is not None:
e.setAttribute('revision', r.revision) e.setAttribute('revision', r.revision)
if r.projecthookName is not None:
ph = doc.createElement('projecthook')
ph.setAttribute('name', r.projecthookName)
ph.setAttribute('revision', r.projecthookRevision)
e.appendChild(ph)
def _ParseGroups(self, groups): def _ParseGroups(self, groups):
return [x for x in re.split(r'[,\s]+', groups) if x] return [x for x in re.split(r'[,\s]+', groups) if x]
@ -638,13 +629,7 @@ class XmlManifest(object):
if revision == '': if revision == '':
revision = None revision = None
manifestUrl = self.manifestProject.config.GetString('remote.origin.url') manifestUrl = self.manifestProject.config.GetString('remote.origin.url')
projecthookName = None return _XmlRemote(name, alias, fetch, manifestUrl, review, revision)
projecthookRevision = None
for n in node.childNodes:
if n.nodeName == 'projecthook':
projecthookName, projecthookRevision = self._ParseProjectHooks(n)
break
return _XmlRemote(name, alias, fetch, manifestUrl, review, revision, projecthookName, projecthookRevision)
def _ParseDefault(self, node): def _ParseDefault(self, node):
""" """
@ -948,8 +933,3 @@ class XmlManifest(object):
diff['added'].append(toProjects[proj]) diff['added'].append(toProjects[proj])
return diff return diff
def _ParseProjectHooks(self, node):
name = self._reqatt(node, 'name')
revision = self._reqatt(node, 'revision')
return name, revision

View File

@ -69,6 +69,27 @@ def not_rev(r):
def sq(r): def sq(r):
return "'" + r.replace("'", "'\''") + "'" return "'" + r.replace("'", "'\''") + "'"
_project_hook_list = None
def _ProjectHooks():
"""List the hooks present in the 'hooks' directory.
These hooks are project hooks and are copied to the '.git/hooks' directory
of all subprojects.
This function caches the list of hooks (based on the contents of the
'repo/hooks' directory) on the first call.
Returns:
A list of absolute paths to all of the files in the hooks directory.
"""
global _project_hook_list
if _project_hook_list is None:
d = os.path.realpath(os.path.abspath(os.path.dirname(__file__)))
d = os.path.join(d, 'hooks')
_project_hook_list = [os.path.join(d, x) for x in os.listdir(d)]
return _project_hook_list
class DownloadedChange(object): class DownloadedChange(object):
_commit_cache = None _commit_cache = None
@ -788,7 +809,7 @@ class Project(object):
out = StatusColoring(self.config) out = StatusColoring(self.config)
if not output_redir == None: if not output_redir == None:
out.redirect(output_redir) out.redirect(output_redir)
out.project('project %-40s', self.relpath + '/') out.project('project %-40s', self.relpath + '/ ')
branch = self.CurrentBranch branch = self.CurrentBranch
if branch is None: if branch is None:
@ -2085,7 +2106,7 @@ class Project(object):
if GitCommand(self, cmd).Wait() != 0: if GitCommand(self, cmd).Wait() != 0:
raise GitError('%s merge %s ' % (self.name, head)) raise GitError('%s merge %s ' % (self.name, head))
def _InitGitDir(self, mirror_git=None, MirrorOverride=False): def _InitGitDir(self, mirror_git=None):
if not os.path.exists(self.gitdir): if not os.path.exists(self.gitdir):
# Initialize the bare repository, which contains all of the objects. # Initialize the bare repository, which contains all of the objects.
@ -2127,38 +2148,11 @@ class Project(object):
for key in ['user.name', 'user.email']: for key in ['user.name', 'user.email']:
if m.Has(key, include_defaults=False): if m.Has(key, include_defaults=False):
self.config.SetString(key, m.GetString(key)) self.config.SetString(key, m.GetString(key))
if self.manifest.IsMirror and not MirrorOverride: if self.manifest.IsMirror:
self.config.SetString('core.bare', 'true') self.config.SetString('core.bare', 'true')
else: else:
self.config.SetString('core.bare', None) self.config.SetString('core.bare', None)
def _ProjectHooks(self, remote, repodir):
"""List the hooks present in the 'hooks' directory.
These hooks are project hooks and are copied to the '.git/hooks' directory
of all subprojects.
The remote projecthooks supplement/overrule any stockhook making it possible to
have a combination of hooks both from the remote projecthook and
.repo/hooks directories.
Returns:
A list of absolute paths to all of the files in the hooks directory and
projecthooks files, excluding the .git folder.
"""
hooks = {}
d = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'hooks')
hooks = dict([(x, os.path.join(d, x)) for x in os.listdir(d)])
if remote is not None:
if remote.projecthookName is not None:
d = os.path.abspath('%s/projecthooks/%s/%s' % (repodir, remote.name, remote.projecthookName))
if os.path.isdir(d):
hooks.update(dict([(x, os.path.join(d, x)) for x in os.listdir(d)]))
if hooks.has_key('.git'):
del hooks['.git']
return hooks.values()
def _UpdateHooks(self): def _UpdateHooks(self):
if os.path.exists(self.gitdir): if os.path.exists(self.gitdir):
self._InitHooks() self._InitHooks()
@ -2167,10 +2161,7 @@ class Project(object):
hooks = os.path.realpath(self._gitdir_path('hooks')) hooks = os.path.realpath(self._gitdir_path('hooks'))
if not os.path.exists(hooks): if not os.path.exists(hooks):
os.makedirs(hooks) os.makedirs(hooks)
pr = None for stock_hook in _ProjectHooks():
if self is not self.manifest.manifestProject:
pr = self.manifest.remotes.get(self.remote.name)
for stock_hook in self._ProjectHooks(pr, self.manifest.repodir):
name = os.path.basename(stock_hook) name = os.path.basename(stock_hook)
if name in ('commit-msg',) and not self.remote.review \ if name in ('commit-msg',) and not self.remote.review \

2
repo
View File

@ -462,7 +462,7 @@ def _DownloadBundle(url, local, quiet):
try: try:
r = urllib.request.urlopen(url) r = urllib.request.urlopen(url)
except urllib.error.HTTPError as e: except urllib.error.HTTPError as e:
if e.code in [403, 404]: if e.code in [401, 403, 404]:
return False return False
_print('fatal: Cannot get %s' % url, file=sys.stderr) _print('fatal: Cannot get %s' % url, file=sys.stderr)
_print('fatal: HTTP error %s' % e.code, file=sys.stderr) _print('fatal: HTTP error %s' % e.code, file=sys.stderr)

View File

@ -32,7 +32,7 @@ else:
from color import Coloring from color import Coloring
from command import InteractiveCommand, MirrorSafeCommand from command import InteractiveCommand, MirrorSafeCommand
from error import ManifestParseError from error import ManifestParseError
from project import SyncBuffer, MetaProject from project import SyncBuffer
from git_config import GitConfig from git_config import GitConfig
from git_command import git_require, MIN_GIT_VERSION from git_command import git_require, MIN_GIT_VERSION
@ -374,52 +374,6 @@ to update the working directory files.
print(' rm -r %s/.repo' % self.manifest.topdir) print(' rm -r %s/.repo' % self.manifest.topdir)
print('and try again.') print('and try again.')
def _SyncProjectHooks(self, opt, repodir):
"""Downloads the defined hooks supplied in the projecthooks element
"""
# Always delete projecthooks and re-download for every new init.
projecthooksdir = os.path.join(repodir, 'projecthooks')
if os.path.exists(projecthooksdir):
shutil.rmtree(projecthooksdir)
for remotename in self.manifest.remotes:
r = self.manifest.remotes.get(remotename)
if r.projecthookName is not None and r.projecthookRevision is not None:
projecthookurl = r.resolvedFetchUrl.rstrip('/') + '/' + r.projecthookName
ph = MetaProject(manifest = self.manifest,
name = r.projecthookName,
gitdir = os.path.join(projecthooksdir,'%s/%s.git' % (remotename, r.projecthookName)),
worktree = os.path.join(projecthooksdir,'%s/%s' % (remotename, r.projecthookName)))
ph.revisionExpr = r.projecthookRevision
is_new = not ph.Exists
if is_new:
if not opt.quiet:
print('Get projecthook %s' % \
GitConfig.ForUser().UrlInsteadOf(projecthookurl), file=sys.stderr)
ph._InitGitDir(MirrorOverride=True)
phr = ph.GetRemote(remotename)
phr.name = 'origin'
phr.url = projecthookurl
phr.ResetFetch()
phr.Save()
if not ph.Sync_NetworkHalf(quiet=opt.quiet, is_new=is_new, clone_bundle=False):
print('fatal: cannot obtain projecthook %s' % phr.url, file=sys.stderr)
# Better delete the git dir if we created it; otherwise next
# time (when user fixes problems) we won't go through the "is_new" logic.
if is_new:
shutil.rmtree(ph.gitdir)
sys.exit(1)
syncbuf = SyncBuffer(ph.config)
ph.Sync_LocalHalf(syncbuf)
syncbuf.Finish()
def Execute(self, opt, args): def Execute(self, opt, args):
git_require(MIN_GIT_VERSION, fail=True) git_require(MIN_GIT_VERSION, fail=True)
@ -435,7 +389,6 @@ to update the working directory files.
self._SyncManifest(opt) self._SyncManifest(opt)
self._LinkManifest(opt.manifest_name) self._LinkManifest(opt.manifest_name)
self._SyncProjectHooks(opt, self.manifest.repodir)
if os.isatty(0) and os.isatty(1) and not self.manifest.IsMirror: if os.isatty(0) and os.isatty(1) and not self.manifest.IsMirror:
if opt.config_name or self._ShouldConfigureUser(): if opt.config_name or self._ShouldConfigureUser():