For bug #157393, fix up ebuild path normalization so that it's compatible with portdb...
[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 opts, pargs = getopt.getopt(sys.argv[1:], '', ['debug', 'force'])
16 debug = ("--debug",'') in opts
17 force = ("--force",'') in opts
18
19 if "merge" in pargs:
20         print "Disabling noauto in features... merge disables it. (qmerge doesn't)"
21         os.environ["FEATURES"] = os.environ.get("FEATURES", "") + " -noauto"
22
23 os.environ["PORTAGE_CALLER"]="ebuild"
24 try:
25         import portage
26 except ImportError:
27         sys.path.insert(0, "/usr/lib/portage/pym")
28         import portage
29
30 import portage_util, portage_const
31
32 # do this _after_ 'import portage' to prevent unnecessary tracing
33 if debug and "python-trace" in portage.features:
34         import portage_debug
35         portage_debug.set_trace(True)
36
37 if portage.settings["NOCOLOR"] in ("yes","true") or not sys.stdout.isatty():
38         import output
39         output.nocolor()
40
41 ebuild = pargs.pop(0)
42 if not os.path.isabs(ebuild):
43         mycwd = os.getcwd()
44         # Try to get the non-canonical path from the PWD evironment variable, since
45         # the canonical path returned from os.getcwd() may may be unusable in
46         # cases where the directory stucture is built from symlinks.
47         if "PWD" in os.environ and os.environ["PWD"] != mycwd and \
48                 os.path.realpath(os.environ["PWD"]) == mycwd:
49                 mycwd = portage.normalize_path(os.environ["PWD"])
50         ebuild = os.path.join(mycwd, ebuild)
51 # portdbapi uses the canonical path for the base of the portage tree, but
52 # subdirectories of the base can be built from symlinks (like crossdev does).
53 ebuild_portdir = os.path.realpath(os.path.dirname(os.path.dirname(ebuild)))
54 ebuild = os.path.join(ebuild_portdir, *ebuild.split(os.path.sep)[-2:])
55
56 if not os.path.exists(ebuild):
57         print "'%s' does not exist." % ebuild
58         sys.exit(1)
59
60 ebuild_split = ebuild.split("/")
61 del ebuild_split[-2]
62 cpv = "/".join(ebuild_split[-2:])[:-7]
63
64 if not portage.catpkgsplit(cpv):
65         print "!!! %s does not follow correct package syntax." % (cpv)
66         sys.exit(1)
67
68 if ebuild.startswith(portage.root + portage_const.VDB_PATH):
69         mytree = "vartree"
70
71         portage_ebuild = portage.db[portage.root][mytree].dbapi.findname(cpv)
72
73         if os.path.realpath(portage_ebuild) != ebuild:
74                 print "!!! Portage seems to think that %s is at %s" % (cpv, portage_ebuild)
75                 sys.exit(1)
76
77 else:
78         mytree = "porttree"
79
80         portage_ebuild = portage.portdb.findname(cpv)
81
82         if not portage_ebuild or portage_ebuild != ebuild:
83                 overlay = "/".join(ebuild_split[:-2])
84                 os.environ["PORTDIR_OVERLAY"] = os.environ.get("PORTDIR_OVERLAY","") + " " + overlay
85                 print "Appending %s to PORTDIR_OVERLAY..." % overlay
86                 portage.close_portdbapi_caches()
87                 reload(portage)
88                 portage_ebuild = portage.portdb.findname(cpv)
89
90                 if not portage_ebuild or portage_ebuild != ebuild:
91                         print "!!! %s does not seem to have a valid PORTDIR structure." % overlay
92                         sys.exit(1)
93
94
95 if len(pargs) > 1 and "config" in pargs:
96         print "config must be called on it's own, not combined with any other phase"
97         sys.exit(1)
98
99 def discard_digests(myebuild, mysettings, mydbapi):
100         """Discard all distfiles digests for the given ebuild.  This is useful when
101         upstream has changed the identity of the distfiles and the user would
102         otherwise have to manually remove the Manifest and files/digest-* files in
103         order to ensure correct results."""
104         try:
105                 portage._doebuild_manifest_exempt_depend += 1
106                 pkgdir = os.path.dirname(myebuild)
107                 fetchlist_dict = portage.FetchlistDict(pkgdir, mysettings, mydbapi)
108                 cat, pkg = pkgdir.split(os.sep)[-2:]
109                 cpv = cat + "/" + os.path.basename(myebuild)[:-7]
110                 from portage_manifest import Manifest
111                 mf = Manifest(pkgdir, mysettings["DISTDIR"],
112                         fetchlist_dict=fetchlist_dict)
113                 mf.create(requiredDistfiles=None,
114                         assumeDistHashesSometimes=True, assumeDistHashesAlways=True)
115                 distfiles = fetchlist_dict[cpv]
116                 for myfile in distfiles:
117                         try:
118                                 del mf.fhashdict["DIST"][myfile]
119                         except KeyError:
120                                 pass
121                 mf.write()
122         finally:
123                 portage._doebuild_manifest_exempt_depend -= 1
124
125 for arg in pargs:
126         try:
127                 tmpsettings = portage.config(clone=portage.settings)
128                 if arg == "digest" and force:
129                         discard_digests(ebuild, tmpsettings, portage.portdb)
130                 a = portage.doebuild(ebuild, arg, portage.root, tmpsettings,
131                         debug=debug, tree=mytree)
132         except KeyboardInterrupt:
133                 print "Interrupted."
134                 a = 1
135         except KeyError:
136                 # aux_get error
137                 a = 1
138         if a == None:
139                 print "Could not run the required binary?"
140                 a = 127
141         if a:
142                 sys.exit(a)