Disable manifest1_compat for ebuild --force digest.
[portage.git] / bin / ebuild
1 #!/usr/bin/python -O
2 # Copyright 1999-2006 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4 # $Header: /var/cvsroot/gentoo-src/portage/bin/ebuild,v 1.18.2.3 2005/05/07 04:32:59 ferringb Exp $
5
6 import getopt, os, sys
7
8 if len(sys.argv) <= 2:
9         print "Usage: ebuild <ebuild file> <command> [command] ..."
10         print ""
11         print "See the ebuild(1) man page for more info"
12         sys.exit(1)
13
14
15 try:
16         opts, pargs = getopt.getopt(sys.argv[1:], '', ['debug', 'force'])
17 except getopt.GetoptError, e:
18         print e
19         sys.exit(1)
20 debug = ("--debug",'') in opts
21 force = ("--force",'') in opts
22
23 if "merge" in pargs:
24         print "Disabling noauto in features... merge disables it. (qmerge doesn't)"
25         os.environ["FEATURES"] = os.environ.get("FEATURES", "") + " -noauto"
26
27 os.environ["PORTAGE_CALLER"]="ebuild"
28 try:
29         import portage
30 except ImportError:
31         from os import path as osp
32         sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
33         import portage
34
35 import portage.util, portage.const
36 import portage.dep
37 portage.dep._dep_check_strict = True
38
39 # do this _after_ 'import portage' to prevent unnecessary tracing
40 if debug and "python-trace" in portage.features:
41         import portage.debug
42         portage.debug.set_trace(True)
43
44 if portage.settings["NOCOLOR"] in ("yes","true") or not sys.stdout.isatty():
45         portage.output.nocolor()
46
47 ebuild = pargs.pop(0)
48 if not os.path.isabs(ebuild):
49         mycwd = os.getcwd()
50         # Try to get the non-canonical path from the PWD evironment variable, since
51         # the canonical path returned from os.getcwd() may may be unusable in
52         # cases where the directory stucture is built from symlinks.
53         if "PWD" in os.environ and os.environ["PWD"] != mycwd and \
54                 os.path.realpath(os.environ["PWD"]) == mycwd:
55                 mycwd = portage.normalize_path(os.environ["PWD"])
56         ebuild = os.path.join(mycwd, ebuild)
57 ebuild = portage.normalize_path(ebuild)
58 # portdbapi uses the canonical path for the base of the portage tree, but
59 # subdirectories of the base can be built from symlinks (like crossdev does).
60 ebuild_portdir = os.path.realpath(
61         os.path.dirname(os.path.dirname(os.path.dirname(ebuild))))
62 ebuild = os.path.join(ebuild_portdir, *ebuild.split(os.path.sep)[-3:])
63
64 # Make sure that portdb.findname() returns the correct ebuild.
65 if ebuild_portdir not in portage.portdb.porttrees:
66         os.environ["PORTDIR_OVERLAY"] = \
67                 os.environ.get("PORTDIR_OVERLAY","") + " " + ebuild_portdir
68         print "Appending %s to PORTDIR_OVERLAY..." % ebuild_portdir
69         portage.close_portdbapi_caches()
70         reload(portage)
71 del portage.portdb.porttrees[1:]
72 if ebuild_portdir != portage.portdb.porttree_root:
73         portage.portdb.porttrees.append(ebuild_portdir)
74
75 if not os.path.exists(ebuild):
76         print "'%s' does not exist." % ebuild
77         sys.exit(1)
78
79 ebuild_split = ebuild.split("/")
80 del ebuild_split[-2]
81 cpv = "/".join(ebuild_split[-2:])[:-7]
82
83 if not portage.catpkgsplit(cpv):
84         print "!!! %s does not follow correct package syntax." % (cpv)
85         sys.exit(1)
86
87 if ebuild.startswith(portage.root + portage.const.VDB_PATH):
88         mytree = "vartree"
89
90         portage_ebuild = portage.db[portage.root][mytree].dbapi.findname(cpv)
91
92         if os.path.realpath(portage_ebuild) != ebuild:
93                 print "!!! Portage seems to think that %s is at %s" % (cpv, portage_ebuild)
94                 sys.exit(1)
95
96 else:
97         mytree = "porttree"
98
99         portage_ebuild = portage.portdb.findname(cpv)
100
101         if not portage_ebuild or portage_ebuild != ebuild:
102                 print "!!! %s does not seem to have a valid PORTDIR structure." % ebuild
103                 sys.exit(1)
104
105 if len(pargs) > 1 and "config" in pargs:
106         print "config must be called on it's own, not combined with any other phase"
107         sys.exit(1)
108
109 def discard_digests(myebuild, mysettings, mydbapi):
110         """Discard all distfiles digests for the given ebuild.  This is useful when
111         upstream has changed the identity of the distfiles and the user would
112         otherwise have to manually remove the Manifest and files/digest-* files in
113         order to ensure correct results."""
114         try:
115                 portage._doebuild_manifest_exempt_depend += 1
116                 pkgdir = os.path.dirname(myebuild)
117                 fetchlist_dict = portage.FetchlistDict(pkgdir, mysettings, mydbapi)
118                 cat, pkg = pkgdir.split(os.sep)[-2:]
119                 cpv = cat + "/" + os.path.basename(myebuild)[:-7]
120                 from portage.manifest import Manifest
121                 mf = Manifest(pkgdir, mysettings["DISTDIR"],
122                         fetchlist_dict=fetchlist_dict, manifest1_compat=False)
123                 mf.create(requiredDistfiles=None,
124                         assumeDistHashesSometimes=True, assumeDistHashesAlways=True)
125                 distfiles = fetchlist_dict[cpv]
126                 for myfile in distfiles:
127                         try:
128                                 del mf.fhashdict["DIST"][myfile]
129                         except KeyError:
130                                 pass
131                 mf.write()
132         finally:
133                 portage._doebuild_manifest_exempt_depend -= 1
134
135 tmpsettings = portage.config(clone=portage.settings)
136 if "test" in pargs:
137         # This variable is a signal to config.regenerate() to
138         # indicate that the test phase should be enabled regardless
139         # of problems such as masked "test" USE flag.
140         tmpsettings["EBUILD_FORCE_TEST"] = "1"
141         tmpsettings.backup_changes("EBUILD_FORCE_TEST")
142         if "test" not in tmpsettings.features:
143                 tmpsettings.features.append("test")
144                 tmpsettings.features.sort()
145                 tmpsettings["FEATURES"] = " ".join(tmpsettings.features)
146                 tmpsettings.backup_changes("FEATURES")
147
148 build_dir_phases = set(["setup", "unpack", "compile",
149         "test", "install", "package", "rpm"])
150
151 def stale_env_warning():
152         if "clean" not in pargs and \
153                 "noauto" not in tmpsettings.features and \
154                 tmpsettings.get("PORTAGE_QUIET") != "1" and \
155                 build_dir_phases.intersection(pargs):
156                 portage.doebuild_environment(ebuild, "setup", portage.root,
157                         tmpsettings, debug, 1, portage.portdb)
158                 env_filename = os.path.join(tmpsettings["T"], "environment")
159                 if os.path.exists(env_filename):
160                         msg = ("Existing ${T}/environment for '%s' will be sourced. " + \
161                                 "Run 'clean' to start with a fresh environment.") % \
162                                 (tmpsettings["PF"], )
163                         from textwrap import wrap
164                         msg = wrap(msg, 70)
165                         for x in msg:
166                                 portage.writemsg(">>> %s\n" % x)
167
168 from portage.exception import UnsupportedAPIException
169 checked_for_stale_env = False
170
171 for arg in pargs:
172         try:
173                 if not checked_for_stale_env and arg not in ("digest","manifest"):
174                         # This has to go after manifest generation since otherwise
175                         # aux_get() might fail due to invalid ebuild digests.
176                         stale_env_warning()
177                         checked_for_stale_env = True
178
179                 if arg == "digest" and force:
180                         discard_digests(ebuild, tmpsettings, portage.portdb)
181                 a = portage.doebuild(ebuild, arg, portage.root, tmpsettings,
182                         debug=debug, tree=mytree)
183         except KeyboardInterrupt:
184                 print "Interrupted."
185                 a = 1
186         except KeyError:
187                 # aux_get error
188                 a = 1
189         except UnsupportedAPIException, e:
190                 from textwrap import wrap
191                 msg = wrap(str(e), 70)
192                 del e
193                 for x in msg:
194                         portage.writemsg("!!! %s\n" % x, noiselevel=-1)
195                 a = 1
196         if a == None:
197                 print "Could not run the required binary?"
198                 a = 127
199         if a:
200                 sys.exit(a)