The Android Open Source Project | cf31fe9 | 2008-10-21 07:00:00 -0700 | [diff] [blame] | 1 | # |
| 2 | # Copyright (C) 2008 The Android Open Source Project |
| 3 | # |
| 4 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | # you may not use this file except in compliance with the License. |
| 6 | # You may obtain a copy of the License at |
| 7 | # |
| 8 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | # |
| 10 | # Unless required by applicable law or agreed to in writing, software |
| 11 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | # See the License for the specific language governing permissions and |
| 14 | # limitations under the License. |
| 15 | |
| 16 | import os |
| 17 | import sys |
| 18 | import tempfile |
| 19 | |
| 20 | from command import Command |
| 21 | from error import GitError, NoSuchProjectError |
| 22 | from git_config import IsId |
| 23 | from import_tar import ImportTar |
| 24 | from import_zip import ImportZip |
| 25 | from project import Project |
| 26 | from remote import Remote |
| 27 | |
| 28 | def _ToCommit(project, rev): |
| 29 | return project.bare_git.rev_parse('--verify', '%s^0' % rev) |
| 30 | |
| 31 | def _Missing(project, rev): |
| 32 | return project._revlist('--objects', rev, '--not', '--all') |
| 33 | |
| 34 | |
| 35 | class ComputeSnapshotCheck(Command): |
| 36 | common = False |
| 37 | helpSummary = "Compute the check value for a new snapshot" |
| 38 | helpUsage = """ |
| 39 | %prog -p NAME -v VERSION -s FILE [options] |
| 40 | """ |
| 41 | helpDescription = """ |
| 42 | %prog computes and then displays the proper check value for a |
| 43 | snapshot, so it can be pasted into the manifest file for a project. |
| 44 | """ |
| 45 | |
| 46 | def _Options(self, p): |
| 47 | g = p.add_option_group('Snapshot description options') |
| 48 | g.add_option('-p', '--project', |
| 49 | dest='project', metavar='NAME', |
| 50 | help='destination project name') |
| 51 | g.add_option('-v', '--version', |
| 52 | dest='version', metavar='VERSION', |
| 53 | help='upstream version/revision identifier') |
| 54 | g.add_option('-s', '--snapshot', |
| 55 | dest='snapshot', metavar='PATH', |
| 56 | help='local tarball path') |
| 57 | g.add_option('--new-project', |
| 58 | dest='new_project', action='store_true', |
| 59 | help='destinition is a new project') |
| 60 | g.add_option('--keep', |
| 61 | dest='keep_git', action='store_true', |
| 62 | help='keep the temporary git repository') |
| 63 | |
| 64 | g = p.add_option_group('Base revision grafting options') |
| 65 | g.add_option('--prior', |
| 66 | dest='prior', metavar='COMMIT', |
| 67 | help='prior revision checksum') |
| 68 | |
| 69 | g = p.add_option_group('Path mangling options') |
| 70 | g.add_option('--strip-prefix', |
| 71 | dest='strip_prefix', metavar='PREFIX', |
| 72 | help='remove prefix from all paths on import') |
| 73 | g.add_option('--insert-prefix', |
| 74 | dest='insert_prefix', metavar='PREFIX', |
| 75 | help='insert prefix before all paths on import') |
| 76 | |
| 77 | |
| 78 | def _Compute(self, opt): |
| 79 | try: |
| 80 | real_project = self.GetProjects([opt.project])[0] |
| 81 | except NoSuchProjectError: |
| 82 | if opt.new_project: |
| 83 | print >>sys.stderr, \ |
| 84 | "warning: project '%s' does not exist" % opt.project |
| 85 | else: |
| 86 | raise NoSuchProjectError(opt.project) |
| 87 | |
| 88 | self._tmpdir = tempfile.mkdtemp() |
| 89 | project = Project(manifest = self.manifest, |
| 90 | name = opt.project, |
| 91 | remote = Remote('origin'), |
| 92 | gitdir = os.path.join(self._tmpdir, '.git'), |
| 93 | worktree = self._tmpdir, |
| 94 | relpath = opt.project, |
| 95 | revision = 'refs/heads/master') |
| 96 | project._InitGitDir() |
| 97 | |
| 98 | url = 'file://%s' % os.path.abspath(opt.snapshot) |
| 99 | |
| 100 | imp = None |
| 101 | for cls in [ImportTar, ImportZip]: |
| 102 | if cls.CanAccept(url): |
| 103 | imp = cls() |
| 104 | break |
| 105 | if not imp: |
| 106 | print >>sys.stderr, 'error: %s unsupported' % opt.snapshot |
| 107 | sys.exit(1) |
| 108 | |
| 109 | imp.SetProject(project) |
| 110 | imp.SetVersion(opt.version) |
| 111 | imp.AddUrl(url) |
| 112 | |
| 113 | if opt.prior: |
| 114 | if opt.new_project: |
| 115 | if not IsId(opt.prior): |
| 116 | print >>sys.stderr, 'error: --prior=%s not valid' % opt.prior |
| 117 | sys.exit(1) |
| 118 | else: |
| 119 | try: |
| 120 | opt.prior = _ToCommit(real_project, opt.prior) |
| 121 | missing = _Missing(real_project, opt.prior) |
| 122 | except GitError, e: |
| 123 | print >>sys.stderr,\ |
| 124 | 'error: --prior=%s not valid\n%s' \ |
| 125 | % (opt.prior, e) |
| 126 | sys.exit(1) |
| 127 | if missing: |
| 128 | print >>sys.stderr,\ |
| 129 | 'error: --prior=%s is valid, but is not reachable' \ |
| 130 | % opt.prior |
| 131 | sys.exit(1) |
| 132 | imp.SetParent(opt.prior) |
| 133 | |
| 134 | src = opt.strip_prefix |
| 135 | dst = opt.insert_prefix |
| 136 | if src or dst: |
| 137 | if src is None: |
| 138 | src = '' |
| 139 | if dst is None: |
| 140 | dst = '' |
| 141 | imp.RemapPath(src, dst) |
| 142 | commitId = imp.Import() |
| 143 | |
| 144 | print >>sys.stderr,"%s\t%s" % (commitId, imp.version) |
| 145 | return project |
| 146 | |
| 147 | def Execute(self, opt, args): |
| 148 | if args \ |
| 149 | or not opt.project \ |
| 150 | or not opt.version \ |
| 151 | or not opt.snapshot: |
| 152 | self.Usage() |
| 153 | |
| 154 | success = False |
| 155 | project = None |
| 156 | try: |
| 157 | self._tmpdir = None |
| 158 | project = self._Compute(opt) |
| 159 | finally: |
| 160 | if project and opt.keep_git: |
| 161 | print 'GIT_DIR = %s' % (project.gitdir) |
| 162 | elif self._tmpdir: |
| 163 | for root, dirs, files in os.walk(self._tmpdir, topdown=False): |
| 164 | for name in files: |
| 165 | os.remove(os.path.join(root, name)) |
| 166 | for name in dirs: |
| 167 | os.rmdir(os.path.join(root, name)) |
| 168 | os.rmdir(self._tmpdir) |
| 169 | |