Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 196043
Collapse All | Expand All

(-)pym/portage.py (-27 / +67 lines)
Lines 7160-7165 Link Here
7160
	This class provides an interface to the installed package database
7160
	This class provides an interface to the installed package database
7161
	At present this is implemented as a text backend in /var/db/pkg.
7161
	At present this is implemented as a text backend in /var/db/pkg.
7162
	"""
7162
	"""
7163
7164
	import re
7165
	_normalize_needed = re.compile(r'//|^[^/]|.+/$')
7166
7163
	def __init__(self, cat, pkg, myroot, mysettings, treetype=None,
7167
	def __init__(self, cat, pkg, myroot, mysettings, treetype=None,
7164
		vartree=None):
7168
		vartree=None):
7165
		"""
7169
		"""
Lines 7293-7299 Link Here
7293
		mylines=myc.readlines()
7297
		mylines=myc.readlines()
7294
		myc.close()
7298
		myc.close()
7295
		null_byte = "\0"
7299
		null_byte = "\0"
7296
		contents_file = os.path.join(self.dbdir, "CONTENTS")
7300
		normalize_needed = self._normalize_needed
7301
		myroot = self.myroot
7302
		if myroot == os.path.sep:
7303
			myroot = None
7297
		pos = 0
7304
		pos = 0
7298
		for line in mylines:
7305
		for line in mylines:
7299
			pos += 1
7306
			pos += 1
Lines 7307-7314 Link Here
7307
			# we do this so we can remove from non-root filesystems
7314
			# we do this so we can remove from non-root filesystems
7308
			# (use the ROOT var to allow maintenance on other partitions)
7315
			# (use the ROOT var to allow maintenance on other partitions)
7309
			try:
7316
			try:
7310
				mydat[1] = normalize_path(os.path.join(
7317
				if normalize_needed.match(mydat[1]):
7311
					self.myroot, mydat[1].lstrip(os.path.sep)))
7318
					mydat[1] = normalize_path(mydat[1])
7319
					if not mydat[1].startswith(os.path.sep):
7320
						mydat[1] = os.path.sep + mydat[1]
7321
				if myroot:
7322
					mydat[1] = os.path.join(myroot, mydat[1].lstrip(os.path.sep))
7312
				if mydat[0]=="obj":
7323
				if mydat[0]=="obj":
7313
					#format: type, mtime, md5sum
7324
					#format: type, mtime, md5sum
7314
					pkgfiles[" ".join(mydat[1:-2])]=[mydat[0], mydat[-1], mydat[-2]]
7325
					pkgfiles[" ".join(mydat[1:-2])]=[mydat[0], mydat[-1], mydat[-2]]
Lines 7712-7720 Link Here
7712
7723
7713
	def isowner(self,filename,destroot):
7724
	def isowner(self,filename,destroot):
7714
		""" 
7725
		""" 
7715
		Check if filename is a new file or belongs to this package
7726
		Check if a file belongs to this package. This may
7716
		(for this or a previous version)
7727
		result in a stat call for the parent directory of
7717
		
7728
		every installed file, since the inode numbers are
7729
		used to work around the problem of ambiguous paths
7730
		caused by symlinked directories. The results of
7731
		stat calls are cached to optimize multiple calls
7732
		to this method.
7733
7718
		@param filename:
7734
		@param filename:
7719
		@type filename:
7735
		@type filename:
7720
		@param destroot:
7736
		@param destroot:
Lines 7731-7753 Link Here
7731
		if pkgfiles and destfile in pkgfiles:
7747
		if pkgfiles and destfile in pkgfiles:
7732
			return True
7748
			return True
7733
		if pkgfiles:
7749
		if pkgfiles:
7750
			# Use stat rather than lstat since we want to follow
7751
			# any symlinks to the real parent directory.
7752
			parent_path = os.path.dirname(destfile)
7734
			try:
7753
			try:
7735
				mylstat = os.lstat(destfile)
7754
				parent_stat = os.stat(parent_path)
7736
			except EnvironmentError, e:
7755
			except EnvironmentError, e:
7737
				if e.errno != errno.ENOENT:
7756
				if e.errno != errno.ENOENT:
7738
					raise
7757
					raise
7739
				del e
7758
				del e
7740
				return True
7759
				return False
7741
			if self._contents_inodes is None:
7760
			if self._contents_inodes is None:
7742
				self._contents_inodes = set()
7761
				self._contents_inodes = {}
7762
				parent_paths = set()
7743
				for x in pkgfiles:
7763
				for x in pkgfiles:
7764
					p_path = os.path.dirname(x)
7765
					if p_path in parent_paths:
7766
						continue
7767
					parent_paths.add(p_path)
7744
					try:
7768
					try:
7745
						lstat = os.lstat(x)
7769
						s = os.stat(p_path)
7746
						self._contents_inodes.add((lstat.st_dev, lstat.st_ino))
7747
					except OSError:
7770
					except OSError:
7748
						pass
7771
						pass
7749
			if (mylstat.st_dev, mylstat.st_ino) in self._contents_inodes:
7772
					else:
7750
				 return True
7773
						inode_key = (s.st_dev, s.st_ino)
7774
						# Use lists of paths in case multiple
7775
						# paths reference the same inode.
7776
						p_path_list = self._contents_inodes.get(inode_key)
7777
						if p_path_list is None:
7778
							p_path_list = []
7779
							self._contents_inodes[inode_key] = p_path_list
7780
						if p_path not in p_path_list:
7781
							p_path_list.append(p_path)
7782
			p_path_list = self._contents_inodes.get(
7783
				(parent_stat.st_dev, parent_stat.st_ino))
7784
			if p_path_list:
7785
				basename = os.path.basename(destfile)
7786
				for p_path in p_path_list:
7787
					x = os.path.join(p_path, basename)
7788
					if x in pkgfiles:
7789
						return True
7751
7790
7752
		return False
7791
		return False
7753
7792
Lines 7979-7989 Link Here
7979
				print "Searching all installed packages for file collisions..."
8018
				print "Searching all installed packages for file collisions..."
7980
				print "Press Ctrl-C to Stop"
8019
				print "Press Ctrl-C to Stop"
7981
				print
8020
				print
7982
				""" Note: The isowner calls result in a stat call for *every*
7983
				single installed file, since the inode numbers are used to work
7984
				around the problem of ambiguous paths caused by symlinked files
7985
				and/or directories.  Though it is slow, it is as accurate as
7986
				possible."""
7987
				found_owner = False
8021
				found_owner = False
7988
				for cpv in self.vartree.dbapi.cpv_all():
8022
				for cpv in self.vartree.dbapi.cpv_all():
7989
					cat, pkg = catsplit(cpv)
8023
					cat, pkg = catsplit(cpv)
Lines 8037-8051 Link Here
8037
			" Add \"collision-protect\" to FEATURES in make.conf" + \
8071
			" Add \"collision-protect\" to FEATURES in make.conf" + \
8038
			" if you would like the merge to abort in cases like this."
8072
			" if you would like the merge to abort in cases like this."
8039
			if self.settings.get("PORTAGE_QUIET") != "1":
8073
			if self.settings.get("PORTAGE_QUIET") != "1":
8040
				msg += " If you have determined that one or more of the" + \
8074
				msg += " You can use a command such as" + \
8041
				" files actually belong to another installed package then" + \
8075
				" \\`portageq owners / <filename>\\` to identify the" + \
8042
				" go to http://bugs.gentoo.org and report it as a bug." + \
8076
				" installed package that owns a file. If portageq" + \
8043
				" Be sure to identify both this package and the other" + \
8077
				" reports that only one package owns a file then do NOT" + \
8044
				" installed package in the bug report. Use a command such" + \
8078
				" file a bug report. A bug report is only useful if it" + \
8045
				" as \\`equery belongs <filename>\\` to identify the" + \
8079
				" identifies at least two or more packages that are known" + \
8046
				" installed package that owns a file. Do NOT file a bug" + \
8080
				" install the same file(s). If a collision occurs and you" + \
8047
				" without reporting exactly which two packages install" + \
8081
				" can not explain where the file came from then you" + \
8048
				" the same file(s)."
8082
				" should simply ignore the collision since there is not" + \
8083
				" enough information to determine if a real problem" + \
8084
				" exists. Please do NOT file a bug report at" + \
8085
				" http://bugs.gentoo.org unless you report exactly which" + \
8086
				" two packages install the same file(s). Once again," + \
8087
				" please do NOT file a bug report unless you have" + \
8088
				" completely understood the above message."
8049
8089
8050
			self.settings["EBUILD_PHASE"] = "preinst"
8090
			self.settings["EBUILD_PHASE"] = "preinst"
8051
			cmd = "source '%s/isolated-functions.sh' ; " % PORTAGE_BIN_PATH
8091
			cmd = "source '%s/isolated-functions.sh' ; " % PORTAGE_BIN_PATH
(-)bin/portageq (-1 / +66 lines)
Lines 124-129 Link Here
124
124
125
metadata.uses_root = True
125
metadata.uses_root = True
126
126
127
def owners(argv):
128
	"""<root> [<filename>]+
129
	Given a list of files, print the packages that own the files and which
130
	files belong to each package. Files owned by a package are listed on
131
	the lines below it, indented by a single tab character (\\t). All file
132
	paths must start with <root>. Returns 1 if no owners could be found,
133
	and 0 otherwise.
134
	"""
135
	if len(argv) < 2:
136
		sys.stderr.write("ERROR: insufficient parameters!\n")
137
		sys.stderr.flush()
138
		return 2
139
140
	from portage import catsplit, dblink
141
	settings = portage.settings
142
	root = settings["ROOT"]
143
	vardb = portage.db[root]["vartree"].dbapi
144
145
	cwd = None
146
	try:
147
		cwd = os.getcwd()
148
	except OSError:
149
		pass
150
151
	files = []
152
	for f in argv[1:]:
153
		f = portage.normalize_path(f)
154
		if not f.startswith(os.path.sep):
155
			if cwd is None:
156
				sys.stderr.write("ERROR: cwd does not exist!\n")
157
				sys.stderr.flush()
158
				return 2
159
			f = os.path.join(cwd, f)
160
			f = portage.normalize_path(f)
161
		if not f.startswith(root):
162
			sys.stderr.write("ERROR: file paths must begin with <root>!\n")
163
			sys.stderr.flush()
164
			return 2
165
		files.append(f[len(root):])
166
167
	found_owner = False
168
	for cpv in vardb.cpv_all():
169
		cat, pkg = catsplit(cpv)
170
		mylink = dblink(cat, pkg, root, settings, vartree=vardb.vartree)
171
		myfiles = []
172
		for f in files:
173
			if mylink.isowner(f, root):
174
				myfiles.append(f)
175
		if myfiles:
176
			found_owner = True
177
			sys.stdout.write("%s\n" % cpv)
178
			for f in myfiles:
179
				sys.stdout.write("\t%s\n" % \
180
					os.path.join(root, f.lstrip(os.path.sep)))
181
			sys.stdout.flush()
182
	if not found_owner:
183
		sys.stderr.write("None of the installed packages claim the file(s).\n")
184
		sys.stderr.flush()
185
		return 1
186
	return 0
187
188
owners.uses_root = True
189
127
def best_visible(argv):
190
def best_visible(argv):
128
	"""<root> [<category/package>]+
191
	"""<root> [<category/package>]+
129
	Returns category/package-version (without .ebuild).
192
	Returns category/package-version (without .ebuild).
Lines 334-340 Link Here
334
			import portage
397
			import portage
335
		if uses_root:
398
		if uses_root:
336
			sys.argv[2] = portage.root
399
			sys.argv[2] = portage.root
337
		function(sys.argv[2:])
400
		retval = function(sys.argv[2:])
401
		if retval:
402
			sys.exit(retval)
338
	except KeyError:
403
	except KeyError:
339
		usage(sys.argv)
404
		usage(sys.argv)
340
		sys.exit(os.EX_USAGE)
405
		sys.exit(os.EX_USAGE)

Return to bug 196043