Пример #1
0
def xtermTitleReset():
	global default_xterm_title
	if default_xterm_title is None:
		prompt_command = os.environ.get('PROMPT_COMMAND')
		if prompt_command == "":
			default_xterm_title = ""
		elif prompt_command is not None:
			if dotitles and \
				'TERM' in os.environ and \
				_legal_terms_re.match(os.environ['TERM']) is not None and \
				sys.__stderr__.isatty():
				from portage.process import find_binary, spawn
				shell = os.environ.get("SHELL")
				if not shell or not os.access(shell, os.EX_OK):
					shell = find_binary("sh")
				if shell:
					spawn([shell, "-c", prompt_command], env=os.environ,
						fd_pipes={
							0: portage._get_stdin().fileno(),
							1: sys.__stderr__.fileno(),
							2: sys.__stderr__.fileno()
						})
				else:
					os.system(prompt_command)
			return
		else:
			pwd = os.environ.get('PWD','')
			home = os.environ.get('HOME', '')
			if home != '' and pwd.startswith(home):
				pwd = '~' + pwd[len(home):]
			default_xterm_title = '\x1b]0;%s@%s:%s\x07' % (
				os.environ.get('LOGNAME', ''),
				os.environ.get('HOSTNAME', '').split('.', 1)[0], pwd)
	xtermTitle(default_xterm_title, raw=True)
Пример #2
0
def portage_func(func, args, exit_status=0):
	# we don't care about the output of the programs,
	# just their exit value and the state of $D
	global env
	f = open('/dev/null', 'wb')
	fd_pipes = {0:0,1:f.fileno(),2:f.fileno()}
	spawn([func] + args.split(), env=env, fd_pipes=fd_pipes)
	f.close()
Пример #3
0
def portage_func(func, args, exit_status=0):
	# we don't care about the output of the programs,
	# just their exit value and the state of $D
	global env
	f = open('/dev/null', 'wb')
	fd_pipes = {0:0,1:f.fileno(),2:f.fileno()}
	def pre_exec():
		os.chdir(env['S'])
	spawn([func] + args.split(), env=env,
		fd_pipes=fd_pipes, pre_exec=pre_exec)
	f.close()
Пример #4
0
def set_term_size(lines, columns, fd):
	"""
	Set the number of lines and columns for the tty that is connected to fd.
	For portability, this simply calls `stty rows $lines columns $columns`.
	"""
	from portage.process import spawn
	cmd = ["stty", "rows", str(lines), "columns", str(columns)]
	try:
		spawn(cmd, env=os.environ, fd_pipes={0:fd})
	except CommandNotFound:
		writemsg(_("portage: stty: command not found\n"), noiselevel=-1)
Пример #5
0
def file_get(baseurl=None,
             dest=None,
             conn=None,
             fcmd=None,
             filename=None,
             fcmd_vars=None):
    """Takes a base url to connect to and read from.
    URI should be in the form <proto>://[user[:pass]@]<site>[:port]<path>"""

    if not fcmd:

        warnings.warn(
            "Use of portage.getbinpkg.file_get() without the fcmd "
            "parameter is deprecated",
            DeprecationWarning,
            stacklevel=2,
        )

        return file_get_lib(baseurl, dest, conn)

    variables = {}

    if fcmd_vars is not None:
        variables.update(fcmd_vars)

    if "DISTDIR" not in variables:
        if dest is None:
            raise portage.exception.MissingParameter(
                _("%s is missing required '%s' key") %
                ("fcmd_vars", "DISTDIR"))
        variables["DISTDIR"] = dest

    if "URI" not in variables:
        if baseurl is None:
            raise portage.exception.MissingParameter(
                _("%s is missing required '%s' key") % ("fcmd_vars", "URI"))
        variables["URI"] = baseurl

    if "FILE" not in variables:
        if filename is None:
            filename = os.path.basename(variables["URI"])
        variables["FILE"] = filename

    from portage.util import varexpand
    from portage.process import spawn

    myfetch = portage.util.shlex_split(fcmd)
    myfetch = [varexpand(x, mydict=variables) for x in myfetch]
    fd_pipes = {
        0: portage._get_stdin().fileno(),
        1: sys.__stdout__.fileno(),
        2: sys.__stdout__.fileno(),
    }
    sys.__stdout__.flush()
    sys.__stderr__.flush()
    retval = spawn(myfetch, env=os.environ.copy(), fd_pipes=fd_pipes)
    if retval != os.EX_OK:
        sys.stderr.write(_("Fetcher exited with a failure condition.\n"))
        return 0
    return 1
Пример #6
0
	def start(self, settings):
		"""
		Start the SOCKSv5 server.

		@param settings: Portage settings instance (used to determine
		paths)
		@type settings: portage.config
		"""
		try:
			import asyncio  # NOQA
		except ImportError:
			raise NotImplementedError('SOCKSv5 proxy requires asyncio module')

		tmpdir = os.path.join(settings['PORTAGE_TMPDIR'], 'portage')
		ensure_dirs_kwargs = {}
		if portage.secpass >= 1:
			ensure_dirs_kwargs['gid'] = portage_gid
			ensure_dirs_kwargs['mode'] = 0o70
			ensure_dirs_kwargs['mask'] = 0
		portage.util.ensure_dirs(tmpdir, **ensure_dirs_kwargs)

		self.socket_path = os.path.join(tmpdir,
				'.portage.%d.net.sock' % os.getpid())
		server_bin = os.path.join(settings['PORTAGE_BIN_PATH'], 'socks5-server.py')
		spawn_kwargs = {}
		# The portage_uid check solves EPERM failures in Travis CI.
		if portage.data.secpass > 1 and os.geteuid() != portage_uid:
			spawn_kwargs.update(
				uid=portage_uid,
				gid=portage_gid,
				groups=userpriv_groups,
				umask=0o077)
		self._pids = spawn([_python_interpreter, server_bin, self.socket_path],
				returnpid=True, **spawn_kwargs)
Пример #7
0
def file_get(baseurl, dest, conn=None, fcmd=None):
    """(baseurl,dest,fcmd=) -- Takes a base url to connect to and read from.
	URI should be in the form <proto>://[user[:pass]@]<site>[:port]<path>"""

    if not fcmd:
        return file_get_lib(baseurl, dest, conn)

    variables = {
        "DISTDIR": dest,
        "URI": baseurl,
        "FILE": os.path.basename(baseurl)
    }

    from portage.util import varexpand
    from portage.process import spawn
    myfetch = portage.util.shlex_split(fcmd)
    myfetch = [varexpand(x, mydict=variables) for x in myfetch]
    fd_pipes = {
        0: sys.stdin.fileno(),
        1: sys.stdout.fileno(),
        2: sys.stdout.fileno()
    }
    retval = spawn(myfetch, env=os.environ.copy(), fd_pipes=fd_pipes)
    if retval != os.EX_OK:
        sys.stderr.write(_("Fetcher exited with a failure condition.\n"))
        return 0
    return 1
Пример #8
0
def file_get(baseurl,dest,conn=None,fcmd=None,filename=None):
	"""(baseurl,dest,fcmd=) -- Takes a base url to connect to and read from.
	URI should be in the form <proto>://[user[:pass]@]<site>[:port]<path>"""

	if not fcmd:

		warnings.warn("Use of portage.getbinpkg.file_get() without the fcmd "
			"parameter is deprecated", DeprecationWarning, stacklevel=2)

		return file_get_lib(baseurl,dest,conn)
	if not filename:
		filename = os.path.basename(baseurl)

	variables = {
		"DISTDIR": dest,
		"URI":     baseurl,
		"FILE":    filename
	}

	from portage.util import varexpand
	from portage.process import spawn
	myfetch = portage.util.shlex_split(fcmd)
	myfetch = [varexpand(x, mydict=variables) for x in myfetch]
	fd_pipes= {
		0:sys.__stdin__.fileno(),
		1:sys.__stdout__.fileno(),
		2:sys.__stdout__.fileno()
	}
	sys.__stdout__.flush()
	sys.__stderr__.flush()
	retval = spawn(myfetch, env=os.environ.copy(), fd_pipes=fd_pipes)
	if retval != os.EX_OK:
		sys.stderr.write(_("Fetcher exited with a failure condition.\n"))
		return 0
	return 1
Пример #9
0
def file_get(baseurl,dest,conn=None,fcmd=None):
	"""(baseurl,dest,fcmd=) -- Takes a base url to connect to and read from.
	URI should be in the form <proto>://[user[:pass]@]<site>[:port]<path>"""

	if not fcmd:
		return file_get_lib(baseurl,dest,conn)

	variables = {
		"DISTDIR": dest,
		"URI":     baseurl,
		"FILE":    os.path.basename(baseurl)
	}

	from portage.util import varexpand
	from portage.process import spawn
	myfetch = portage.util.shlex_split(fcmd)
	myfetch = [varexpand(x, mydict=variables) for x in myfetch]
	fd_pipes= {
		0:sys.stdin.fileno(),
		1:sys.stdout.fileno(),
		2:sys.stdout.fileno()
	}
	retval = spawn(myfetch, env=os.environ.copy(), fd_pipes=fd_pipes)
	if retval != os.EX_OK:
		sys.stderr.write(_("Fetcher exited with a failure condition.\n"))
		return 0
	return 1
Пример #10
0
	def update_index(self, mymanifests, myupdates):
		'''Update the vcs's modified index if it is needed

		@param mymanifests: manifest files updated
		@param myupdates: other files updated'''
		# It's not safe to use the git commit -a option since there might
		# be some modified files elsewhere in the working tree that the
		# user doesn't want to commit. Therefore, call git update-index
		# in order to ensure that the index is updated with the latest
		# versions of all new and modified files in the relevant portion
		# of the working tree.
		myfiles = mymanifests + myupdates
		myfiles.sort()
		update_index_cmd = ["git", "update-index"]
		update_index_cmd.extend(f.lstrip("./") for f in myfiles)
		if self.options.pretend:
			print("(%s)" % (" ".join(update_index_cmd),))
		else:
			retval = spawn(update_index_cmd, env=os.environ)
			if retval != os.EX_OK:
				writemsg_level(
					"!!! Exiting on %s (shell) "
					"error code: %s\n" % (self.vcs_settings.vcs, retval),
					level=logging.ERROR, noiselevel=-1)
				sys.exit(retval)
Пример #11
0
            async def watch_pid():

                with asyncio.get_child_watcher() as watcher:
                    pids = spawn([true_binary], returnpid=True)
                    watcher.add_child_handler(pids[0], callback, *args_tuple)
                    self.assertEqual((await future),
                                     (pids[0], os.EX_OK, args_tuple))
Пример #12
0
    def start(self, settings):
        """
		Start the SOCKSv5 server.

		@param settings: Portage settings instance (used to determine
		paths)
		@type settings: portage.config
		"""
        try:
            import asyncio  # NOQA
        except ImportError:
            raise NotImplementedError('SOCKSv5 proxy requires asyncio module')

        self.socket_path = os.path.join(settings['PORTAGE_TMPDIR'],
                                        '.portage.%d.net.sock' % os.getpid())
        server_bin = os.path.join(settings['PORTAGE_BIN_PATH'],
                                  'socks5-server.py')
        spawn_kwargs = {}
        # The portage_uid check solves EPERM failures in Travis CI.
        if portage.data.secpass > 1 and os.geteuid() != portage_uid:
            spawn_kwargs.update(uid=portage_uid,
                                gid=portage_gid,
                                groups=userpriv_groups,
                                umask=0o077)
        self._pids = spawn([_python_interpreter, server_bin, self.socket_path],
                           returnpid=True,
                           **spawn_kwargs)
Пример #13
0
	def testChildWatcher(self):
		true_binary = find_binary("true")
		self.assertNotEqual(true_binary, None)

		initial_policy = asyncio.get_event_loop_policy()
		if not isinstance(initial_policy, DefaultEventLoopPolicy):
			asyncio.set_event_loop_policy(DefaultEventLoopPolicy())

		try:
			try:
				asyncio.set_child_watcher(None)
			except NotImplementedError:
				pass
			else:
				self.assertTrue(False)

			args_tuple = ('hello', 'world')

			loop = asyncio.get_event_loop()
			future = loop.create_future()

			def callback(pid, returncode, *args):
				future.set_result((pid, returncode, args))

			with asyncio.get_child_watcher() as watcher:
				pids = spawn([true_binary], returnpid=True)
				watcher.add_child_handler(pids[0], callback, *args_tuple)

				self.assertEqual(
					loop.run_until_complete(future),
					(pids[0], os.EX_OK, args_tuple))
		finally:
			asyncio.set_event_loop_policy(initial_policy)
Пример #14
0
def xtermTitleReset():
    global default_xterm_title
    if default_xterm_title is None:
        prompt_command = os.environ.get("PROMPT_COMMAND")
        if prompt_command == "":
            default_xterm_title = ""
        elif prompt_command is not None:
            if (
                dotitles
                and "TERM" in os.environ
                and _legal_terms_re.match(os.environ["TERM"]) is not None
                and sys.__stderr__.isatty()
            ):
                from portage.process import find_binary, spawn

                shell = os.environ.get("SHELL")
                if not shell or not os.access(shell, os.EX_OK):
                    shell = find_binary("sh")
                if shell:
                    spawn(
                        [shell, "-c", prompt_command],
                        env=os.environ,
                        fd_pipes={
                            0: portage._get_stdin().fileno(),
                            1: sys.__stderr__.fileno(),
                            2: sys.__stderr__.fileno(),
                        },
                    )
                else:
                    os.system(prompt_command)
            return
        else:
            pwd = os.environ.get("PWD", "")
            home = os.environ.get("HOME", "")
            if home != "" and pwd.startswith(home):
                pwd = "~" + pwd[len(home) :]
            default_xterm_title = "\x1b]0;%s@%s:%s\x07" % (
                os.environ.get("LOGNAME", ""),
                os.environ.get("HOSTNAME", "").split(".", 1)[0],
                pwd,
            )
    xtermTitle(default_xterm_title, raw=True)
Пример #15
0
	def add_manifest(self, mymanifests, myheaders, myupdates, myremoved,
					commitmessage):
		myfiles = mymanifests[:]
		# If there are no header (SVN/CVS keywords) changes in
		# the files, this Manifest commit must include the
		# other (yet uncommitted) files.
		if not myheaders:
			myfiles += myupdates
			myfiles += myremoved
		myfiles.sort()

		fd, commitmessagefile = tempfile.mkstemp(".repoman.msg")
		mymsg = os.fdopen(fd, "wb")
		mymsg.write(_unicode_encode(commitmessage))
		mymsg.close()

		commit_cmd = []
		if self.options.pretend and self.vcs_settings.vcs is None:
			# substitute a bogus value for pretend output
			commit_cmd.append("cvs")
		else:
			commit_cmd.append(self.vcs_settings.vcs)
		commit_cmd.extend(self.vcs_settings.vcs_global_opts)
		commit_cmd.append("commit")
		commit_cmd.extend(self.vcs_settings.vcs_local_opts)
		if self.vcs_settings.vcs == "hg":
			commit_cmd.extend(["--logfile", commitmessagefile])
			commit_cmd.extend(myfiles)
		else:
			commit_cmd.extend(["-F", commitmessagefile])
			commit_cmd.extend(f.lstrip("./") for f in myfiles)

		try:
			if self.options.pretend:
				print("(%s)" % (" ".join(commit_cmd),))
			else:
				retval = spawn(commit_cmd, env=self.repo_settings.commit_env)
				if retval != os.EX_OK:
					if self.repo_settings.repo_config.sign_commit and self.vcs_settings.vcs == 'git' and \
						not git_supports_gpg_sign():
						# Inform user that newer git is needed (bug #403323).
						logging.error(
							"Git >=1.7.9 is required for signed commits!")

					writemsg_level(
						"!!! Exiting on %s (shell) "
						"error code: %s\n" % (self.vcs_settings.vcs, retval),
						level=logging.ERROR, noiselevel=-1)
					sys.exit(retval)
		finally:
			try:
				os.unlink(commitmessagefile)
			except OSError:
				pass
Пример #16
0
def file_get(baseurl=None, dest=None, conn=None, fcmd=None, filename=None,
	fcmd_vars=None):
	"""Takes a base url to connect to and read from.
	URI should be in the form <proto>://[user[:pass]@]<site>[:port]<path>"""

	if not fcmd:

		warnings.warn("Use of portage.getbinpkg.file_get() without the fcmd "
			"parameter is deprecated", DeprecationWarning, stacklevel=2)

		return file_get_lib(baseurl, dest, conn)

	variables = {}

	if fcmd_vars is not None:
		variables.update(fcmd_vars)

	if "DISTDIR" not in variables:
		if dest is None:
			raise portage.exception.MissingParameter(
				_("%s is missing required '%s' key") %
				("fcmd_vars", "DISTDIR"))
		variables["DISTDIR"] = dest

	if "URI" not in variables:
		if baseurl is None:
			raise portage.exception.MissingParameter(
				_("%s is missing required '%s' key") %
				("fcmd_vars", "URI"))
		variables["URI"] = baseurl

	if "FILE" not in variables:
		if filename is None:
			filename = os.path.basename(variables["URI"])
		variables["FILE"] = filename

	from portage.util import varexpand
	from portage.process import spawn
	myfetch = portage.util.shlex_split(fcmd)
	myfetch = [varexpand(x, mydict=variables) for x in myfetch]
	fd_pipes = {
		0: portage._get_stdin().fileno(),
		1: sys.__stdout__.fileno(),
		2: sys.__stdout__.fileno()
	}
	sys.__stdout__.flush()
	sys.__stderr__.flush()
	retval = spawn(myfetch, env=os.environ.copy(), fd_pipes=fd_pipes)
	if retval != os.EX_OK:
		sys.stderr.write(_("Fetcher exited with a failure condition.\n"))
		return 0
	return 1
Пример #17
0
	def priming_commit(self, myupdates, myremoved, commitmessage):
		myfiles = myupdates + myremoved
		fd, commitmessagefile = tempfile.mkstemp(".repoman.msg")
		mymsg = os.fdopen(fd, "wb")
		mymsg.write(_unicode_encode(commitmessage))
		mymsg.close()

		separator = '-' * 78

		print()
		print(green("Using commit message:"))
		print(green(separator))
		print(commitmessage)
		print(green(separator))
		print()

		# Having a leading ./ prefix on file paths can trigger a bug in
		# the cvs server when committing files to multiple directories,
		# so strip the prefix.
		myfiles = [f.lstrip("./") for f in myfiles]

		commit_cmd = [self.vcs_settings.vcs]
		commit_cmd.extend(self.vcs_settings.vcs_global_opts)
		commit_cmd.append("commit")
		commit_cmd.extend(self.vcs_settings.vcs_local_opts)
		commit_cmd.extend(["-F", commitmessagefile])
		commit_cmd.extend(myfiles)

		try:
			if self.options.pretend:
				print("(%s)" % (" ".join(commit_cmd),))
			else:
				retval = spawn(commit_cmd, env=self.repo_settings.commit_env)
				if retval != os.EX_OK:
					writemsg_level(
						"!!! Exiting on %s (shell) "
						"error code: %s\n" % (self.vcs_settings.vcs, retval),
						level=logging.ERROR, noiselevel=-1)
					sys.exit(retval)
		finally:
			try:
				os.unlink(commitmessagefile)
			except OSError:
				pass
Пример #18
0
	def commit(self, myfiles, commitmessagefile):
		'''Hg commit function

		@param commitfiles: list of files to commit
		@param commitmessagefile: file containing the commit message
		@returns: The sub-command exit value or 0
		'''
		commit_cmd = []
		commit_cmd.append(self.vcs)
		commit_cmd.extend(self.vcs_settings.vcs_global_opts)
		commit_cmd.append("commit")
		commit_cmd.extend(self.vcs_settings.vcs_local_opts)
		commit_cmd.extend(["--logfile", commitmessagefile])
		commit_cmd.extend(myfiles)

		if self.options.pretend:
			print("(%s)" % (" ".join(commit_cmd),))
			return 0
		else:
			retval = spawn(commit_cmd, env=self.repo_settings.commit_env)
		return retval
Пример #19
0
    def commit(self, myfiles, commitmessagefile):
        """Hg commit function

        @param commitfiles: list of files to commit
        @param commitmessagefile: file containing the commit message
        @returns: The sub-command exit value or 0
        """
        commit_cmd = []
        commit_cmd.append(self.vcs)
        commit_cmd.extend(self.vcs_settings.vcs_global_opts)
        commit_cmd.append("commit")
        commit_cmd.extend(self.vcs_settings.vcs_local_opts)
        commit_cmd.extend(["--logfile", commitmessagefile])
        commit_cmd.extend(myfiles)

        if self.options.pretend:
            print("(%s)" % (" ".join(commit_cmd), ))
            return 0
        else:
            retval = spawn(commit_cmd, env=self.repo_settings.commit_env)
        return retval
Пример #20
0
    def start(self, settings):
        """
		Start the SOCKSv5 server.

		@param settings: Portage settings instance (used to determine
		paths)
		@type settings: portage.config
		"""
        try:
            import asyncio  # NOQA
        except ImportError:
            raise NotImplementedError("SOCKSv5 proxy requires asyncio module")

        self.socket_path = os.path.join(settings["PORTAGE_TMPDIR"], ".portage.%d.net.sock" % os.getpid())
        server_bin = os.path.join(settings["PORTAGE_BIN_PATH"], "socks5-server.py")
        self._pids = spawn(
            [_python_interpreter, server_bin, self.socket_path],
            returnpid=True,
            uid=portage_uid,
            gid=portage_gid,
            groups=userpriv_groups,
            umask=0o077,
        )
Пример #21
0
    def start(self, settings):
        """
		Start the SOCKSv5 server.

		@param settings: Portage settings instance (used to determine
		paths)
		@type settings: portage.config
		"""
        try:
            import asyncio  # NOQA
        except ImportError:
            raise NotImplementedError('SOCKSv5 proxy requires asyncio module')

        self.socket_path = os.path.join(settings['PORTAGE_TMPDIR'],
                                        '.portage.%d.net.sock' % os.getpid())
        server_bin = os.path.join(settings['PORTAGE_BIN_PATH'],
                                  'socks5-server.py')
        self._pids = spawn([_python_interpreter, server_bin, self.socket_path],
                           returnpid=True,
                           uid=portage_uid,
                           gid=portage_gid,
                           groups=userpriv_groups,
                           umask=0o077)
Пример #22
0
	def testChildWatcher(self):
		true_binary = find_binary("true")
		self.assertNotEqual(true_binary, None)

		initial_policy = asyncio.get_event_loop_policy()
		if not isinstance(initial_policy, DefaultEventLoopPolicy):
			asyncio.set_event_loop_policy(DefaultEventLoopPolicy())

		loop = None
		try:
			try:
				asyncio.set_child_watcher(None)
			except NotImplementedError:
				pass
			else:
				self.assertTrue(False)

			args_tuple = ('hello', 'world')

			loop = asyncio._wrap_loop()
			future = loop.create_future()

			def callback(pid, returncode, *args):
				future.set_result((pid, returncode, args))

			with asyncio.get_child_watcher() as watcher:
				pids = spawn([true_binary], returnpid=True)
				watcher.add_child_handler(pids[0], callback, *args_tuple)

				self.assertEqual(
					loop.run_until_complete(future),
					(pids[0], os.EX_OK, args_tuple))
		finally:
			asyncio.set_event_loop_policy(initial_policy)
			if loop not in (None, global_event_loop()):
				loop.close()
				self.assertFalse(global_event_loop().is_closed())
Пример #23
0
def movefile(src, dest, newmtime=None, sstat=None, mysettings=None,
		hardlink_candidates=None, encoding=_encodings['fs']):
	"""moves a file from src to dest, preserving all permissions and attributes; mtime will
	be preserved even when moving across filesystems.  Returns mtime as integer on success
	and None on failure.  mtime is expressed in seconds in Python <3.3 and nanoseconds in
	Python >=3.3.  Move is atomic."""

	if mysettings is None:
		mysettings = portage.settings

	src_bytes = _unicode_encode(src, encoding=encoding, errors='strict')
	dest_bytes = _unicode_encode(dest, encoding=encoding, errors='strict')
	xattr_enabled = "xattr" in mysettings.features
	selinux_enabled = mysettings.selinux_enabled()
	if selinux_enabled:
		selinux = _unicode_module_wrapper(_selinux, encoding=encoding)
		_copyfile = selinux.copyfile
		_rename = selinux.rename
	else:
		_copyfile = _shutil.copyfile
		_rename = _os.rename

	lchown = _unicode_func_wrapper(portage.data.lchown, encoding=encoding)
	os = _unicode_module_wrapper(_os,
		encoding=encoding, overrides=_os_overrides)

	try:
		if not sstat:
			sstat = os.lstat(src)

	except SystemExit as e:
		raise
	except Exception as e:
		writemsg("!!! %s\n" % _("Stating source file failed... movefile()"),
			noiselevel=-1)
		writemsg("!!! %s\n" % (e,), noiselevel=-1)
		return None

	destexists = 1
	try:
		dstat = os.lstat(dest)
	except (OSError, IOError):
		dstat = os.lstat(os.path.dirname(dest))
		destexists = 0

	if bsd_chflags:
		if destexists and dstat.st_flags != 0:
			bsd_chflags.lchflags(dest, 0)
		# Use normal stat/chflags for the parent since we want to
		# follow any symlinks to the real parent directory.
		pflags = os.stat(os.path.dirname(dest)).st_flags
		if pflags != 0:
			bsd_chflags.chflags(os.path.dirname(dest), 0)

	if destexists:
		if stat.S_ISLNK(dstat[stat.ST_MODE]):
			try:
				os.unlink(dest)
				destexists = 0
			except SystemExit as e:
				raise
			except Exception as e:
				pass

	if stat.S_ISLNK(sstat[stat.ST_MODE]):
		try:
			target = os.readlink(src)
			if mysettings and "D" in mysettings and \
				target.startswith(mysettings["D"]):
				target = target[len(mysettings["D"])-1:]
			if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]):
				os.unlink(dest)
			try:
				if selinux_enabled:
					selinux.symlink(target, dest, src)
				else:
					os.symlink(target, dest)
			except OSError as e:
				# Some programs will create symlinks automatically, so we have
				# to tolerate these links being recreated during the merge
				# process. In any case, if the link is pointing at the right
				# place, we're in good shape.
				if e.errno not in (errno.ENOENT, errno.EEXIST) or \
					target != os.readlink(dest):
					raise
			lchown(dest, sstat[stat.ST_UID], sstat[stat.ST_GID])

			try:
				_os.unlink(src_bytes)
			except OSError:
				pass

			if sys.hexversion >= 0x3030000:
				try:
					os.utime(dest, ns=(sstat.st_mtime_ns, sstat.st_mtime_ns), follow_symlinks=False)
				except NotImplementedError:
					# utimensat() and lutimes() missing in libc.
					return os.stat(dest, follow_symlinks=False).st_mtime_ns
				else:
					return sstat.st_mtime_ns
			else:
				# utime() in Python <3.3 only works on the target of a symlink, so it's not
				# possible to preserve mtime on symlinks.
				return os.lstat(dest)[stat.ST_MTIME]
		except SystemExit as e:
			raise
		except Exception as e:
			writemsg("!!! %s\n" % _("failed to properly create symlink:"),
				noiselevel=-1)
			writemsg("!!! %s -> %s\n" % (dest, target), noiselevel=-1)
			writemsg("!!! %s\n" % (e,), noiselevel=-1)
			return None

	hardlinked = False
	# Since identical files might be merged to multiple filesystems,
	# so os.link() calls might fail for some paths, so try them all.
	# For atomic replacement, first create the link as a temp file
	# and them use os.rename() to replace the destination.
	if hardlink_candidates:
		head, tail = os.path.split(dest)
		hardlink_tmp = os.path.join(head, ".%s._portage_merge_.%s" % \
			(tail, os.getpid()))
		try:
			os.unlink(hardlink_tmp)
		except OSError as e:
			if e.errno != errno.ENOENT:
				writemsg(_("!!! Failed to remove hardlink temp file: %s\n") % \
					(hardlink_tmp,), noiselevel=-1)
				writemsg("!!! %s\n" % (e,), noiselevel=-1)
				return None
			del e
		for hardlink_src in hardlink_candidates:
			try:
				os.link(hardlink_src, hardlink_tmp)
			except OSError:
				continue
			else:
				try:
					os.rename(hardlink_tmp, dest)
				except OSError as e:
					writemsg(_("!!! Failed to rename %s to %s\n") % \
						(hardlink_tmp, dest), noiselevel=-1)
					writemsg("!!! %s\n" % (e,), noiselevel=-1)
					return None
				hardlinked = True
				try:
					_os.unlink(src_bytes)
				except OSError:
					pass
				break

	renamefailed = 1
	if hardlinked:
		renamefailed = False
	if not hardlinked and (selinux_enabled or sstat.st_dev == dstat.st_dev):
		try:
			if selinux_enabled:
				selinux.rename(src, dest)
			else:
				os.rename(src, dest)
			renamefailed = 0
		except OSError as e:
			if e.errno != errno.EXDEV:
				# Some random error.
				writemsg("!!! %s\n" % _("Failed to move %(src)s to %(dest)s") %
					{"src": src, "dest": dest}, noiselevel=-1)
				writemsg("!!! %s\n" % (e,), noiselevel=-1)
				return None
			# Invalid cross-device-link 'bind' mounted or actually Cross-Device
	if renamefailed:
		if stat.S_ISREG(sstat[stat.ST_MODE]):
			dest_tmp = dest + "#new"
			dest_tmp_bytes = _unicode_encode(dest_tmp, encoding=encoding,
				errors='strict')
			try: # For safety copy then move it over.
				_copyfile(src_bytes, dest_tmp_bytes)
				if xattr_enabled:
					try:
						_copyxattr(src_bytes, dest_tmp_bytes,
							exclude=mysettings.get("PORTAGE_XATTR_EXCLUDE", ""))
					except SystemExit:
						raise
					except:
						msg = _("Failed to copy extended attributes. "
							"In order to avoid this error, set "
							"FEATURES=\"-xattr\" in make.conf.")
						msg = textwrap.wrap(msg, 65)
						for line in msg:
							writemsg("!!! %s\n" % (line,), noiselevel=-1)
						raise
				_apply_stat(sstat, dest_tmp_bytes)
				_rename(dest_tmp_bytes, dest_bytes)
				_os.unlink(src_bytes)
			except SystemExit as e:
				raise
			except Exception as e:
				writemsg("!!! %s\n" % _('copy %(src)s -> %(dest)s failed.') %
					{"src": src, "dest": dest}, noiselevel=-1)
				writemsg("!!! %s\n" % (e,), noiselevel=-1)
				return None
		else:
			#we don't yet handle special, so we need to fall back to /bin/mv
			a = spawn([MOVE_BINARY, '-f', src, dest], env=os.environ)
			if a != os.EX_OK:
				writemsg(_("!!! Failed to move special file:\n"), noiselevel=-1)
				writemsg(_("!!! '%(src)s' to '%(dest)s'\n") % \
					{"src": _unicode_decode(src, encoding=encoding),
					"dest": _unicode_decode(dest, encoding=encoding)}, noiselevel=-1)
				writemsg("!!! %s\n" % a, noiselevel=-1)
				return None # failure

	# In Python <3.3 always use stat_obj[stat.ST_MTIME] for the integral timestamp
	# which is returned, since the stat_obj.st_mtime float attribute rounds *up*
	# if the nanosecond part of the timestamp is 999999881 ns or greater.
	try:
		if hardlinked:
			if sys.hexversion >= 0x3030000:
				newmtime = os.stat(dest).st_mtime_ns
			else:
				newmtime = os.stat(dest)[stat.ST_MTIME]
		else:
			# Note: It is not possible to preserve nanosecond precision
			# (supported in POSIX.1-2008 via utimensat) with the IEEE 754
			# double precision float which only has a 53 bit significand.
			if newmtime is not None:
				if sys.hexversion >= 0x3030000:
					os.utime(dest, ns=(newmtime, newmtime))
				else:
					os.utime(dest, (newmtime, newmtime))
			else:
				if sys.hexversion >= 0x3030000:
					newmtime = sstat.st_mtime_ns
				else:
					newmtime = sstat[stat.ST_MTIME]
				if renamefailed:
					if sys.hexversion >= 0x3030000:
						# If rename succeeded then timestamps are automatically
						# preserved with complete precision because the source
						# and destination inodes are the same. Otherwise, manually
						# update timestamps with nanosecond precision.
						os.utime(dest, ns=(newmtime, newmtime))
					else:
						# If rename succeeded then timestamps are automatically
						# preserved with complete precision because the source
						# and destination inodes are the same. Otherwise, round
						# down to the nearest whole second since python's float
						# st_mtime cannot be used to preserve the st_mtim.tv_nsec
						# field with complete precision. Note that we have to use
						# stat_obj[stat.ST_MTIME] here because the float
						# stat_obj.st_mtime rounds *up* sometimes.
						os.utime(dest, (newmtime, newmtime))
	except OSError:
		# The utime can fail here with EPERM even though the move succeeded.
		# Instead of failing, use stat to return the mtime if possible.
		try:
			if sys.hexversion >= 0x3030000:
				newmtime = os.stat(dest).st_mtime_ns
			else:
				newmtime = os.stat(dest)[stat.ST_MTIME]
		except OSError as e:
			writemsg(_("!!! Failed to stat in movefile()\n"), noiselevel=-1)
			writemsg("!!! %s\n" % dest, noiselevel=-1)
			writemsg("!!! %s\n" % str(e), noiselevel=-1)
			return None

	if bsd_chflags:
		# Restore the flags we saved before moving
		if pflags:
			bsd_chflags.chflags(os.path.dirname(dest), pflags)

	return newmtime
Пример #24
0
def movefile(src, dest, newmtime=None, sstat=None, mysettings=None,
		hardlink_candidates=None, encoding=_encodings['fs']):
	"""moves a file from src to dest, preserving all permissions and attributes; mtime will
	be preserved even when moving across filesystems.  Returns true on success and false on
	failure.  Move is atomic."""
	#print "movefile("+str(src)+","+str(dest)+","+str(newmtime)+","+str(sstat)+")"

	if mysettings is None:
		mysettings = portage.settings

	selinux_enabled = mysettings.selinux_enabled()
	if selinux_enabled:
		selinux = _unicode_module_wrapper(_selinux, encoding=encoding)

	lchown = _unicode_func_wrapper(portage.data.lchown, encoding=encoding)
	os = _unicode_module_wrapper(_os,
		encoding=encoding, overrides=_os_overrides)
	shutil = _unicode_module_wrapper(_shutil, encoding=encoding)

	try:
		if not sstat:
			sstat=os.lstat(src)

	except SystemExit as e:
		raise
	except Exception as e:
		print(_("!!! Stating source file failed... movefile()"))
		print("!!!",e)
		return None

	destexists=1
	try:
		dstat=os.lstat(dest)
	except (OSError, IOError):
		dstat=os.lstat(os.path.dirname(dest))
		destexists=0

	if bsd_chflags:
		if destexists and dstat.st_flags != 0:
			bsd_chflags.lchflags(dest, 0)
		# Use normal stat/chflags for the parent since we want to
		# follow any symlinks to the real parent directory.
		pflags = os.stat(os.path.dirname(dest)).st_flags
		if pflags != 0:
			bsd_chflags.chflags(os.path.dirname(dest), 0)

	if destexists:
		if stat.S_ISLNK(dstat[stat.ST_MODE]):
			try:
				os.unlink(dest)
				destexists=0
			except SystemExit as e:
				raise
			except Exception as e:
				pass

	if stat.S_ISLNK(sstat[stat.ST_MODE]):
		try:
			target=os.readlink(src)
			if mysettings and mysettings["D"]:
				if target.find(mysettings["D"])==0:
					target=target[len(mysettings["D"]):]
			if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]):
				os.unlink(dest)
			if selinux_enabled:
				selinux.symlink(target, dest, src)
			else:
				os.symlink(target,dest)
			lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
			# utime() only works on the target of a symlink, so it's not
			# possible to perserve mtime on symlinks.
			return os.lstat(dest)[stat.ST_MTIME]
		except SystemExit as e:
			raise
		except Exception as e:
			print(_("!!! failed to properly create symlink:"))
			print("!!!",dest,"->",target)
			print("!!!",e)
			return None

	hardlinked = False
	# Since identical files might be merged to multiple filesystems,
	# so os.link() calls might fail for some paths, so try them all.
	# For atomic replacement, first create the link as a temp file
	# and them use os.rename() to replace the destination.
	if hardlink_candidates:
		head, tail = os.path.split(dest)
		hardlink_tmp = os.path.join(head, ".%s._portage_merge_.%s" % \
			(tail, os.getpid()))
		try:
			os.unlink(hardlink_tmp)
		except OSError as e:
			if e.errno != errno.ENOENT:
				writemsg(_("!!! Failed to remove hardlink temp file: %s\n") % \
					(hardlink_tmp,), noiselevel=-1)
				writemsg("!!! %s\n" % (e,), noiselevel=-1)
				return None
			del e
		for hardlink_src in hardlink_candidates:
			try:
				os.link(hardlink_src, hardlink_tmp)
			except OSError:
				continue
			else:
				try:
					os.rename(hardlink_tmp, dest)
				except OSError as e:
					writemsg(_("!!! Failed to rename %s to %s\n") % \
						(hardlink_tmp, dest), noiselevel=-1)
					writemsg("!!! %s\n" % (e,), noiselevel=-1)
					return None
				hardlinked = True
				break

	renamefailed=1
	if hardlinked:
		renamefailed = False
	if not hardlinked and (selinux_enabled or sstat.st_dev == dstat.st_dev):
		try:
			if selinux_enabled:
				selinux.rename(src, dest)
			else:
				os.rename(src,dest)
			renamefailed=0
		except OSError as e:
			if e.errno != errno.EXDEV:
				# Some random error.
				print(_("!!! Failed to move %(src)s to %(dest)s") % {"src": src, "dest": dest})
				print("!!!",e)
				return None
			# Invalid cross-device-link 'bind' mounted or actually Cross-Device
	if renamefailed:
		didcopy=0
		if stat.S_ISREG(sstat[stat.ST_MODE]):
			try: # For safety copy then move it over.
				if selinux_enabled:
					selinux.copyfile(src, dest + "#new")
					selinux.rename(dest + "#new", dest)
				else:
					shutil.copyfile(src,dest+"#new")
					os.rename(dest+"#new",dest)
				didcopy=1
			except SystemExit as e:
				raise
			except Exception as e:
				print(_('!!! copy %(src)s -> %(dest)s failed.') % {"src": src, "dest": dest})
				print("!!!",e)
				return None
		else:
			#we don't yet handle special, so we need to fall back to /bin/mv
			a = spawn([MOVE_BINARY, '-f', src, dest], env=os.environ)
			if a != os.EX_OK:
				writemsg(_("!!! Failed to move special file:\n"), noiselevel=-1)
				writemsg(_("!!! '%(src)s' to '%(dest)s'\n") % \
					{"src": _unicode_decode(src, encoding=encoding),
					"dest": _unicode_decode(dest, encoding=encoding)}, noiselevel=-1)
				writemsg("!!! %s\n" % a, noiselevel=-1)
				return None # failure
		try:
			if didcopy:
				if stat.S_ISLNK(sstat[stat.ST_MODE]):
					lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
				else:
					os.chown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
				os.chmod(dest, stat.S_IMODE(sstat[stat.ST_MODE])) # Sticky is reset on chown
				os.unlink(src)
		except SystemExit as e:
			raise
		except Exception as e:
			print(_("!!! Failed to chown/chmod/unlink in movefile()"))
			print("!!!",dest)
			print("!!!",e)
			return None

	# Always use stat_obj[stat.ST_MTIME] for the integral timestamp which
	# is returned, since the stat_obj.st_mtime float attribute rounds *up*
	# if the nanosecond part of the timestamp is 999999881 ns or greater.
	try:
		if hardlinked:
			newmtime = os.stat(dest)[stat.ST_MTIME]
		else:
			# Note: It is not possible to preserve nanosecond precision
			# (supported in POSIX.1-2008 via utimensat) with the IEEE 754
			# double precision float which only has a 53 bit significand.
			if newmtime is not None:
				os.utime(dest, (newmtime, newmtime))
			else:
				newmtime = sstat[stat.ST_MTIME]
				if renamefailed:
					# If rename succeeded then timestamps are automatically
					# preserved with complete precision because the source
					# and destination inode are the same. Otherwise, round
					# down to the nearest whole second since python's float
					# st_mtime cannot be used to preserve the st_mtim.tv_nsec
					# field with complete precision. Note that we have to use
					# stat_obj[stat.ST_MTIME] here because the float
					# stat_obj.st_mtime rounds *up* sometimes.
					os.utime(dest, (newmtime, newmtime))
	except OSError:
		# The utime can fail here with EPERM even though the move succeeded.
		# Instead of failing, use stat to return the mtime if possible.
		try:
			newmtime = os.stat(dest)[stat.ST_MTIME]
		except OSError as e:
			writemsg(_("!!! Failed to stat in movefile()\n"), noiselevel=-1)
			writemsg("!!! %s\n" % dest, noiselevel=-1)
			writemsg("!!! %s\n" % str(e), noiselevel=-1)
			return None

	if bsd_chflags:
		# Restore the flags we saved before moving
		if pflags:
			bsd_chflags.chflags(os.path.dirname(dest), pflags)

	return newmtime
Пример #25
0
def movefile(src,
             dest,
             newmtime=None,
             sstat=None,
             mysettings=None,
             hardlink_candidates=None,
             encoding=_encodings['fs']):
    """moves a file from src to dest, preserving all permissions and attributes; mtime will
	be preserved even when moving across filesystems.  Returns mtime as integer on success
	and None on failure.  mtime is expressed in seconds in Python <3.3 and nanoseconds in
	Python >=3.3.  Move is atomic."""

    if mysettings is None:
        mysettings = portage.settings

    src_bytes = _unicode_encode(src, encoding=encoding, errors='strict')
    dest_bytes = _unicode_encode(dest, encoding=encoding, errors='strict')
    xattr_enabled = "xattr" in mysettings.features
    selinux_enabled = mysettings.selinux_enabled()
    if selinux_enabled:
        selinux = _unicode_module_wrapper(_selinux, encoding=encoding)
        _copyfile = selinux.copyfile
        _rename = selinux.rename
    else:
        _copyfile = _shutil.copyfile
        _rename = _os.rename

    lchown = _unicode_func_wrapper(portage.data.lchown, encoding=encoding)
    os = _unicode_module_wrapper(_os,
                                 encoding=encoding,
                                 overrides=_os_overrides)

    try:
        if not sstat:
            sstat = os.lstat(src)

    except SystemExit as e:
        raise
    except Exception as e:
        writemsg("!!! %s\n" % _("Stating source file failed... movefile()"),
                 noiselevel=-1)
        writemsg("!!! %s\n" % (e, ), noiselevel=-1)
        return None

    destexists = 1
    try:
        dstat = os.lstat(dest)
    except (OSError, IOError):
        dstat = os.lstat(os.path.dirname(dest))
        destexists = 0

    if bsd_chflags:
        if destexists and dstat.st_flags != 0:
            bsd_chflags.lchflags(dest, 0)
        # Use normal stat/chflags for the parent since we want to
        # follow any symlinks to the real parent directory.
        pflags = os.stat(os.path.dirname(dest)).st_flags
        if pflags != 0:
            bsd_chflags.chflags(os.path.dirname(dest), 0)

    if destexists:
        if stat.S_ISLNK(dstat[stat.ST_MODE]):
            try:
                os.unlink(dest)
                destexists = 0
            except SystemExit as e:
                raise
            except Exception as e:
                pass

    if stat.S_ISLNK(sstat[stat.ST_MODE]):
        try:
            target = os.readlink(src)
            if mysettings and "D" in mysettings and \
             target.startswith(mysettings["D"]):
                target = target[len(mysettings["D"]) - 1:]
            if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]):
                os.unlink(dest)
            try:
                if selinux_enabled:
                    selinux.symlink(target, dest, src)
                else:
                    os.symlink(target, dest)
            except OSError as e:
                # Some programs will create symlinks automatically, so we have
                # to tolerate these links being recreated during the merge
                # process. In any case, if the link is pointing at the right
                # place, we're in good shape.
                if e.errno not in (errno.ENOENT, errno.EEXIST) or \
                 target != os.readlink(dest):
                    raise
            lchown(dest, sstat[stat.ST_UID], sstat[stat.ST_GID])

            try:
                _os.unlink(src_bytes)
            except OSError:
                pass

            if sys.hexversion >= 0x3030000:
                try:
                    os.utime(dest,
                             ns=(sstat.st_mtime_ns, sstat.st_mtime_ns),
                             follow_symlinks=False)
                except NotImplementedError:
                    # utimensat() and lutimes() missing in libc.
                    return os.stat(dest, follow_symlinks=False).st_mtime_ns
                else:
                    return sstat.st_mtime_ns
            else:
                # utime() in Python <3.3 only works on the target of a symlink, so it's not
                # possible to preserve mtime on symlinks.
                return os.lstat(dest)[stat.ST_MTIME]
        except SystemExit as e:
            raise
        except Exception as e:
            writemsg("!!! %s\n" % _("failed to properly create symlink:"),
                     noiselevel=-1)
            writemsg("!!! %s -> %s\n" % (dest, target), noiselevel=-1)
            writemsg("!!! %s\n" % (e, ), noiselevel=-1)
            return None

    hardlinked = False
    # Since identical files might be merged to multiple filesystems,
    # so os.link() calls might fail for some paths, so try them all.
    # For atomic replacement, first create the link as a temp file
    # and them use os.rename() to replace the destination.
    if hardlink_candidates:
        head, tail = os.path.split(dest)
        hardlink_tmp = os.path.join(head, ".%s._portage_merge_.%s" % \
         (tail, os.getpid()))
        try:
            os.unlink(hardlink_tmp)
        except OSError as e:
            if e.errno != errno.ENOENT:
                writemsg(_("!!! Failed to remove hardlink temp file: %s\n") % \
                 (hardlink_tmp,), noiselevel=-1)
                writemsg("!!! %s\n" % (e, ), noiselevel=-1)
                return None
            del e
        for hardlink_src in hardlink_candidates:
            try:
                os.link(hardlink_src, hardlink_tmp)
            except OSError:
                continue
            else:
                try:
                    os.rename(hardlink_tmp, dest)
                except OSError as e:
                    writemsg(_("!!! Failed to rename %s to %s\n") % \
                     (hardlink_tmp, dest), noiselevel=-1)
                    writemsg("!!! %s\n" % (e, ), noiselevel=-1)
                    return None
                hardlinked = True
                try:
                    _os.unlink(src_bytes)
                except OSError:
                    pass
                break

    renamefailed = 1
    if hardlinked:
        renamefailed = False
    if not hardlinked and (selinux_enabled or sstat.st_dev == dstat.st_dev):
        try:
            if selinux_enabled:
                selinux.rename(src, dest)
            else:
                os.rename(src, dest)
            renamefailed = 0
        except OSError as e:
            if e.errno != errno.EXDEV:
                # Some random error.
                writemsg("!!! %s\n" % _("Failed to move %(src)s to %(dest)s") %
                         {
                             "src": src,
                             "dest": dest
                         },
                         noiselevel=-1)
                writemsg("!!! %s\n" % (e, ), noiselevel=-1)
                return None
            # Invalid cross-device-link 'bind' mounted or actually Cross-Device
    if renamefailed:
        if stat.S_ISREG(sstat[stat.ST_MODE]):
            dest_tmp = dest + "#new"
            dest_tmp_bytes = _unicode_encode(dest_tmp,
                                             encoding=encoding,
                                             errors='strict')
            try:  # For safety copy then move it over.
                _copyfile(src_bytes, dest_tmp_bytes)
                if xattr_enabled:
                    try:
                        _copyxattr(src_bytes,
                                   dest_tmp_bytes,
                                   exclude=mysettings.get(
                                       "PORTAGE_XATTR_EXCLUDE",
                                       "security.* system.nfs4_acl"))
                    except SystemExit:
                        raise
                    except:
                        msg = _("Failed to copy extended attributes. "
                                "In order to avoid this error, set "
                                "FEATURES=\"-xattr\" in make.conf.")
                        msg = textwrap.wrap(msg, 65)
                        for line in msg:
                            writemsg("!!! %s\n" % (line, ), noiselevel=-1)
                        raise
                _apply_stat(sstat, dest_tmp_bytes)
                _rename(dest_tmp_bytes, dest_bytes)
                _os.unlink(src_bytes)
            except SystemExit as e:
                raise
            except Exception as e:
                writemsg("!!! %s\n" % _('copy %(src)s -> %(dest)s failed.') % {
                    "src": src,
                    "dest": dest
                },
                         noiselevel=-1)
                writemsg("!!! %s\n" % (e, ), noiselevel=-1)
                return None
        else:
            #we don't yet handle special, so we need to fall back to /bin/mv
            a = spawn([MOVE_BINARY, '-f', src, dest], env=os.environ)
            if a != os.EX_OK:
                writemsg(_("!!! Failed to move special file:\n"),
                         noiselevel=-1)
                writemsg(_("!!! '%(src)s' to '%(dest)s'\n") % \
                 {"src": _unicode_decode(src, encoding=encoding),
                 "dest": _unicode_decode(dest, encoding=encoding)}, noiselevel=-1)
                writemsg("!!! %s\n" % a, noiselevel=-1)
                return None  # failure

    # In Python <3.3 always use stat_obj[stat.ST_MTIME] for the integral timestamp
    # which is returned, since the stat_obj.st_mtime float attribute rounds *up*
    # if the nanosecond part of the timestamp is 999999881 ns or greater.
    try:
        if hardlinked:
            if sys.hexversion >= 0x3030000:
                newmtime = os.stat(dest).st_mtime_ns
            else:
                newmtime = os.stat(dest)[stat.ST_MTIME]
        else:
            # Note: It is not possible to preserve nanosecond precision
            # (supported in POSIX.1-2008 via utimensat) with the IEEE 754
            # double precision float which only has a 53 bit significand.
            if newmtime is not None:
                if sys.hexversion >= 0x3030000:
                    os.utime(dest, ns=(newmtime, newmtime))
                else:
                    os.utime(dest, (newmtime, newmtime))
            else:
                if sys.hexversion >= 0x3030000:
                    newmtime = sstat.st_mtime_ns
                else:
                    newmtime = sstat[stat.ST_MTIME]
                if renamefailed:
                    if sys.hexversion >= 0x3030000:
                        # If rename succeeded then timestamps are automatically
                        # preserved with complete precision because the source
                        # and destination inodes are the same. Otherwise, manually
                        # update timestamps with nanosecond precision.
                        os.utime(dest, ns=(newmtime, newmtime))
                    else:
                        # If rename succeeded then timestamps are automatically
                        # preserved with complete precision because the source
                        # and destination inodes are the same. Otherwise, round
                        # down to the nearest whole second since python's float
                        # st_mtime cannot be used to preserve the st_mtim.tv_nsec
                        # field with complete precision. Note that we have to use
                        # stat_obj[stat.ST_MTIME] here because the float
                        # stat_obj.st_mtime rounds *up* sometimes.
                        os.utime(dest, (newmtime, newmtime))
    except OSError:
        # The utime can fail here with EPERM even though the move succeeded.
        # Instead of failing, use stat to return the mtime if possible.
        try:
            if sys.hexversion >= 0x3030000:
                newmtime = os.stat(dest).st_mtime_ns
            else:
                newmtime = os.stat(dest)[stat.ST_MTIME]
        except OSError as e:
            writemsg(_("!!! Failed to stat in movefile()\n"), noiselevel=-1)
            writemsg("!!! %s\n" % dest, noiselevel=-1)
            writemsg("!!! %s\n" % str(e), noiselevel=-1)
            return None

    if bsd_chflags:
        # Restore the flags we saved before moving
        if pflags:
            bsd_chflags.chflags(os.path.dirname(dest), pflags)

    return newmtime
Пример #26
0
	def perform(self, qa_output):
		myunadded, mydeleted = self._vcs_unadded()

		myautoadd = self._vcs_autoadd(myunadded)

		self._vcs_deleted(mydeleted)

		changes = self.get_vcs_changed(mydeleted)

		mynew, mychanged, myremoved, no_expansion, expansion = changes

		# Manifests need to be regenerated after all other commits, so don't commit
		# them now even if they have changed.
		mymanifests = set()
		myupdates = set()
		for f in mychanged + mynew:
			if "Manifest" == os.path.basename(f):
				mymanifests.add(f)
			else:
				myupdates.add(f)
		myupdates.difference_update(myremoved)
		myupdates = list(myupdates)
		mymanifests = list(mymanifests)
		myheaders = []

		commitmessage = self.options.commitmsg
		if self.options.commitmsgfile:
			try:
				f = io.open(
					_unicode_encode(
						self.options.commitmsgfile,
						encoding=_encodings['fs'], errors='strict'),
					mode='r', encoding=_encodings['content'], errors='replace')
				commitmessage = f.read()
				f.close()
				del f
			except (IOError, OSError) as e:
				if e.errno == errno.ENOENT:
					portage.writemsg(
						"!!! File Not Found:"
						" --commitmsgfile='%s'\n" % self.options.commitmsgfile)
				else:
					raise
		if not commitmessage or not commitmessage.strip():
			commitmessage = self.get_new_commit_message(qa_output)

		commitmessage = commitmessage.rstrip()

		myupdates, broken_changelog_manifests = self.changelogs(
					myupdates, mymanifests, myremoved, mychanged, myautoadd,
					mynew, commitmessage)

		commit_footer = self.get_commit_footer()
		commitmessage += commit_footer

		print("* %s files being committed..." % green(str(len(myupdates))), end=' ')

		if self.vcs_settings.vcs not in ('cvs', 'svn'):
			# With git, bzr and hg, there's never any keyword expansion, so
			# there's no need to regenerate manifests and all files will be
			# committed in one big commit at the end.
			print()
		elif not self.repo_settings.repo_config.thin_manifest:
			self.thick_manifest(myupdates, myheaders, no_expansion, expansion)

		logging.info("myupdates: %s", myupdates)
		logging.info("myheaders: %s", myheaders)

		uq = UserQuery(self.options)
		if self.options.ask and uq.query('Commit changes?', True) != 'Yes':
			print("* aborting commit.")
			sys.exit(128 + signal.SIGINT)

		# Handle the case where committed files have keywords which
		# will change and need a priming commit before the Manifest
		# can be committed.
		if (myupdates or myremoved) and myheaders:
			self.priming_commit(myupdates, myremoved, commitmessage)

		# When files are removed and re-added, the cvs server will put /Attic/
		# inside the $Header path. This code detects the problem and corrects it
		# so that the Manifest will generate correctly. See bug #169500.
		# Use binary mode in order to avoid potential character encoding issues.
		self.clear_attic(myheaders)

		if self.scanner.repolevel == 1:
			utilities.repoman_sez(
				"\"You're rather crazy... "
				"doing the entire repository.\"\n")

		if self.vcs_settings.vcs in ('cvs', 'svn') and (myupdates or myremoved):
			for x in sorted(vcs_files_to_cps(
				chain(myupdates, myremoved, mymanifests),
				self.scanner.repolevel, self.scanner.reposplit, self.scanner.categories)):
				self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x)
				digestgen(mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb)

		elif broken_changelog_manifests:
			for x in broken_changelog_manifests:
				self.repoman_settings["O"] = os.path.join(self.repo_settings.repodir, x)
				digestgen(mysettings=self.repoman_settings, myportdb=self.repo_settings.portdb)

		if self.repo_settings.sign_manifests:
			self.sign_manifest(myupdates, myremoved, mymanifests)

		if self.vcs_settings.vcs == 'git':
			# It's not safe to use the git commit -a option since there might
			# be some modified files elsewhere in the working tree that the
			# user doesn't want to commit. Therefore, call git update-index
			# in order to ensure that the index is updated with the latest
			# versions of all new and modified files in the relevant portion
			# of the working tree.
			myfiles = mymanifests + myupdates
			myfiles.sort()
			update_index_cmd = ["git", "update-index"]
			update_index_cmd.extend(f.lstrip("./") for f in myfiles)
			if self.options.pretend:
				print("(%s)" % (" ".join(update_index_cmd),))
			else:
				retval = spawn(update_index_cmd, env=os.environ)
				if retval != os.EX_OK:
					writemsg_level(
						"!!! Exiting on %s (shell) "
						"error code: %s\n" % (self.vcs_settings.vcs, retval),
						level=logging.ERROR, noiselevel=-1)
					sys.exit(retval)

		self.add_manifest(mymanifests, myheaders, myupdates, myremoved, commitmessage)

		if self.options.quiet:
			return
		print()
		if self.vcs_settings.vcs:
			print("Commit complete.")
		else:
			print(
				"repoman was too scared"
				" by not seeing any familiar version control file"
				" that he forgot to commit anything")
		utilities.repoman_sez(
			"\"If everyone were like you, I'd be out of business!\"\n")
		return