# # Copyright (C) 2008 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import tempfile from command import Command from error import GitError, NoSuchProjectError from git_config import IsId from import_tar import ImportTar from import_zip import ImportZip from project import Project from remote import Remote def _ToCommit(project, rev): return project.bare_git.rev_parse('--verify', '%s^0' % rev) def _Missing(project, rev): return project._revlist('--objects', rev, '--not', '--all') class ComputeSnapshotCheck(Command): common = False helpSummary = "Compute the check value for a new snapshot" helpUsage = """ %prog -p NAME -v VERSION -s FILE [options] """ helpDescription = """ %prog computes and then displays the proper check value for a snapshot, so it can be pasted into the manifest file for a project. """ def _Options(self, p): g = p.add_option_group('Snapshot description options') g.add_option('-p', '--project', dest='project', metavar='NAME', help='destination project name') g.add_option('-v', '--version', dest='version', metavar='VERSION', help='upstream version/revision identifier') g.add_option('-s', '--snapshot', dest='snapshot', metavar='PATH', help='local tarball path') g.add_option('--new-project', dest='new_project', action='store_true', help='destinition is a new project') g.add_option('--keep', dest='keep_git', action='store_true', help='keep the temporary git repository') g = p.add_option_group('Base revision grafting options') g.add_option('--prior', dest='prior', metavar='COMMIT', help='prior revision checksum') g = p.add_option_group('Path mangling options') g.add_option('--strip-prefix', dest='strip_prefix', metavar='PREFIX', help='remove prefix from all paths on import') g.add_option('--insert-prefix', dest='insert_prefix', metavar='PREFIX', help='insert prefix before all paths on import') def _Compute(self, opt): try: real_project = self.GetProjects([opt.project])[0] except NoSuchProjectError: if opt.new_project: print >>sys.stderr, \ "warning: project '%s' does not exist" % opt.project else: raise NoSuchProjectError(opt.project) self._tmpdir = tempfile.mkdtemp() project = Project(manifest = self.manifest, name = opt.project, remote = Remote('origin'), gitdir = os.path.join(self._tmpdir, '.git'), worktree = self._tmpdir, relpath = opt.project, revision = 'refs/heads/master') project._InitGitDir() url = 'file://%s' % os.path.abspath(opt.snapshot) imp = None for cls in [ImportTar, ImportZip]: if cls.CanAccept(url): imp = cls() break if not imp: print >>sys.stderr, 'error: %s unsupported' % opt.snapshot sys.exit(1) imp.SetProject(project) imp.SetVersion(opt.version) imp.AddUrl(url) if opt.prior: if opt.new_project: if not IsId(opt.prior): print >>sys.stderr, 'error: --prior=%s not valid' % opt.prior sys.exit(1) else: try: opt.prior = _ToCommit(real_project, opt.prior) missing = _Missing(real_project, opt.prior) except GitError, e: print >>sys.stderr,\ 'error: --prior=%s not valid\n%s' \ % (opt.prior, e) sys.exit(1) if missing: print >>sys.stderr,\ 'error: --prior=%s is valid, but is not reachable' \ % opt.prior sys.exit(1) imp.SetParent(opt.prior) src = opt.strip_prefix dst = opt.insert_prefix if src or dst: if src is None: src = '' if dst is None: dst = '' imp.RemapPath(src, dst) commitId = imp.Import() print >>sys.stderr,"%s\t%s" % (commitId, imp.version) return project def Execute(self, opt, args): if args \ or not opt.project \ or not opt.version \ or not opt.snapshot: self.Usage() success = False project = None try: self._tmpdir = None project = self._Compute(opt) finally: if project and opt.keep_git: print 'GIT_DIR = %s' % (project.gitdir) elif self._tmpdir: for root, dirs, files in os.walk(self._tmpdir, topdown=False): for name in files: os.remove(os.path.join(root, name)) for name in dirs: os.rmdir(os.path.join(root, name)) os.rmdir(self._tmpdir)