Beispiel #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)
Beispiel #2
0
    def detect_conflicts(options):
        """Determine if the checkout has problems like cvs conflicts.

		If you want more vcs support here just keep adding if blocks...
		This could be better.

		TODO(antarus): Also this should probably not call sys.exit() as
		repoman is run on >1 packages and one failure should not cause
		subsequent packages to fail.

		Args:
			vcs - A string identifying the version control system in use
		Returns: boolean
			(calls sys.exit on fatal problems)
		"""

        cmd = "svn status -u 2>&1 | egrep -v '^.  +.*/digest-[^/]+' | head -n-1"
        msg = "Performing a %s with a little magic grep to check for updates." % green("svn status -u")

        logging.info(msg)
        # Use Popen instead of getstatusoutput(), in order to avoid
        # unicode handling problems (see bug #310789).
        args = [BASH_BINARY, "-c", cmd]
        args = [_unicode_encode(x) for x in args]
        proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        out = _unicode_decode(proc.communicate()[0])
        proc.wait()
        mylines = out.splitlines()
        myupdates = []
        for line in mylines:
            if not line:
                continue

                # [ ] Unmodified (SVN)	[U] Updates		[P] Patches
                # [M] Modified			[A] Added		[R] Removed / Replaced
                # [D] Deleted
            if line[0] not in " UPMARD":
                # Stray Manifest is fine, we will readd it anyway.
                if line[0] == "?" and line[1:].lstrip() == "Manifest":
                    continue
                logging.error(
                    red("!!! Please fix the following issues reported " "from cvs: %s" % green("(U,P,M,A,R,D are ok)"))
                )
                logging.error(red("!!! Note: This is a pretend/no-modify pass..."))
                logging.error(out)
                sys.exit(1)
            elif line[8] == "*":
                myupdates.append(line[9:].lstrip(" 1234567890"))

        if myupdates:
            logging.info(green("Fetching trivial updates..."))
            if options.pretend:
                logging.info("(svn update " + " ".join(myupdates) + ")")
                retval = os.EX_OK
            else:
                retval = os.system("svn update " + " ".join(myupdates))
            if retval != os.EX_OK:
                logging.fatal("!!! svn exited with an error. Terminating.")
                sys.exit(retval)
        return False
Beispiel #3
0
	def detect_conflicts(options):
		"""Determine if the checkout has cvs conflicts.

		TODO(antarus): Also this should probably not call sys.exit() as
		repoman is run on >1 packages and one failure should not cause
		subsequent packages to fail.

		Returns:
			None (calls sys.exit on fatal problems)
		"""

		cmd = ("cvs -n up 2>/dev/null | "
				"egrep '^[^\?] .*' | "
				"egrep -v '^. .*/digest-[^/]+|^cvs server: .* -- ignored$'")
		msg = ("Performing a %s with a little magic grep to check for updates."
				% green("cvs -n up"))

		logging.info(msg)
		# Use Popen instead of getstatusoutput(), in order to avoid
		# unicode handling problems (see bug #310789).
		args = [BASH_BINARY, "-c", cmd]
		args = [_unicode_encode(x) for x in args]
		proc = subprocess.Popen(
			args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
		out = _unicode_decode(proc.communicate()[0])
		proc.wait()
		mylines = out.splitlines()
		myupdates = []
		for line in mylines:
			if not line:
				continue

			# [ ] Unmodified (SVN)	[U] Updates		[P] Patches
			# [M] Modified			[A] Added		[R] Removed / Replaced
			# [D] Deleted
			if line[0] not in " UPMARD":
				# Stray Manifest is fine, we will readd it anyway.
				if line[0] == '?' and line[1:].lstrip() == 'Manifest':
					continue
				logging.error(red(
					"!!! Please fix the following issues reported "
					"from cvs: %s" % green("(U,P,M,A,R,D are ok)")))
				logging.error(red(
					"!!! Note: This is a pretend/no-modify pass..."))
				logging.error(out)
				sys.exit(1)
			elif line[0] in "UP":
				myupdates.append(line[2:])

		if myupdates:
			logging.info(green("Fetching trivial updates..."))
			if options.pretend:
				logging.info("(cvs update " + " ".join(myupdates) + ")")
				retval = os.EX_OK
			else:
				retval = os.system("cvs update " + " ".join(myupdates))
			if retval != os.EX_OK:
				logging.fatal("!!! cvs exited with an error. Terminating.")
				sys.exit(retval)
		return False
Beispiel #4
0
	def detect_conflicts(options):
		"""Determine if the checkout has cvs conflicts.

		TODO(antarus): Also this should probably not call sys.exit() as
		repoman is run on >1 packages and one failure should not cause
		subsequent packages to fail.

		Returns:
			None (calls sys.exit on fatal problems)
		"""

		cmd = (r"cvs -n up 2>/dev/null | "
				r"egrep '^[^\?] .*' | "
				r"egrep -v '^. .*/digest-[^/]+|^cvs server: .* -- ignored$'")
		msg = ("Performing a %s with a little magic grep to check for updates."
				% green("cvs -n up"))

		logging.info(msg)
		# Use Popen instead of getstatusoutput(), in order to avoid
		# unicode handling problems (see bug #310789).
		args = [BASH_BINARY, "-c", cmd]
		args = [_unicode_encode(x) for x in args]
		proc = subprocess.Popen(
			args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
		out = _unicode_decode(proc.communicate()[0])
		proc.wait()
		mylines = out.splitlines()
		myupdates = []
		for line in mylines:
			if not line:
				continue

			# [ ] Unmodified (SVN)	[U] Updates		[P] Patches
			# [M] Modified			[A] Added		[R] Removed / Replaced
			# [D] Deleted
			if line[0] not in " UPMARD":
				# Stray Manifest is fine, we will readd it anyway.
				if line[0] == '?' and line[1:].lstrip() == 'Manifest':
					continue
				logging.error(red(
					"!!! Please fix the following issues reported "
					"from cvs: %s" % green("(U,P,M,A,R,D are ok)")))
				logging.error(red(
					"!!! Note: This is a pretend/no-modify pass..."))
				logging.error(out)
				sys.exit(1)
			elif line[0] in "UP":
				myupdates.append(line[2:])

		if myupdates:
			logging.info(green("Fetching trivial updates..."))
			if options.pretend:
				logging.info("(cvs update " + " ".join(myupdates) + ")")
				retval = os.EX_OK
			else:
				retval = os.system("cvs update " + " ".join(myupdates))
			if retval != os.EX_OK:
				logging.fatal("!!! cvs exited with an error. Terminating.")
				sys.exit(retval)
		return False
def detect_vcs_conflicts(options, vcs):
	"""Determine if the checkout has problems like cvs conflicts.
	
	If you want more vcs support here just keep adding if blocks...
	This could be better.
	
	TODO(antarus): Also this should probably not call sys.exit() as
	repoman is run on >1 packages and one failure should not cause
	subsequent packages to fail.
	
	Args:
		vcs - A string identifying the version control system in use
	Returns:
		None (calls sys.exit on fatal problems)
	"""
	retval = ("","")
	if vcs == 'cvs':
		logging.info("Performing a " + output.green("cvs -n up") + \
			" with a little magic grep to check for updates.")
		retval = subprocess_getstatusoutput("cvs -n up 2>/dev/null | " + \
			"egrep '^[^\?] .*' | " + \
			"egrep -v '^. .*/digest-[^/]+|^cvs server: .* -- ignored$'")
	if vcs == 'svn':
		logging.info("Performing a " + output.green("svn status -u") + \
			" with a little magic grep to check for updates.")
		retval = subprocess_getstatusoutput("svn status -u 2>&1 | " + \
			"egrep -v '^.  +.*/digest-[^/]+' | " + \
			"head -n-1")

	if vcs in ['cvs', 'svn']:
		mylines = retval[1].splitlines()
		myupdates = []
		for line in mylines:
			if not line:
				continue
			if line[0] not in " UPMARD": # unmodified(svn),Updates,Patches,Modified,Added,Removed/Replaced(svn),Deleted(svn)
				# Stray Manifest is fine, we will readd it anyway.
				if line[0] == '?' and line[1:].lstrip() == 'Manifest':
					continue
				logging.error(red("!!! Please fix the following issues reported " + \
					"from cvs: ")+green("(U,P,M,A,R,D are ok)"))
				logging.error(red("!!! Note: This is a pretend/no-modify pass..."))
				logging.error(retval[1])
				sys.exit(1)
			elif vcs == 'cvs' and line[0] in "UP":
				myupdates.append(line[2:])
			elif vcs == 'svn' and line[8] == '*':
				myupdates.append(line[9:].lstrip(" 1234567890"))

		if myupdates:
			logging.info(green("Fetching trivial updates..."))
			if options.pretend:
				logging.info("(" + vcs + " update " + " ".join(myupdates) + ")")
				retval = os.EX_OK
			else:
				retval = os.system(vcs + " update " + " ".join(myupdates))
			if retval != os.EX_OK:
				logging.fatal("!!! " + vcs + " exited with an error. Terminating.")
				sys.exit(retval)
Beispiel #6
0
def detect_vcs_conflicts(options, vcs):
	"""Determine if the checkout has problems like cvs conflicts.
	
	If you want more vcs support here just keep adding if blocks...
	This could be better.
	
	TODO(antarus): Also this should probably not call sys.exit() as
	repoman is run on >1 packages and one failure should not cause
	subsequent packages to fail.
	
	Args:
		vcs - A string identifying the version control system in use
	Returns:
		None (calls sys.exit on fatal problems)
	"""
	retval = ("","")
	if vcs == 'cvs':
		logging.info("Performing a " + output.green("cvs -n up") + \
			" with a little magic grep to check for updates.")
		retval = subprocess_getstatusoutput("cvs -n up 2>&1 | " + \
			"egrep '^[^\?] .*' | " + \
			"egrep -v '^. .*/digest-[^/]+|^cvs server: .* -- ignored$'")
	if vcs == 'svn':
		logging.info("Performing a " + output.green("svn status -u") + \
			" with a little magic grep to check for updates.")
		retval = subprocess_getstatusoutput("svn status -u 2>&1 | " + \
			"egrep -v '^.  +.*/digest-[^/]+' | " + \
			"head -n-1")

	if vcs in ['cvs', 'svn']:
		mylines = retval[1].splitlines()
		myupdates = []
		for line in mylines:
			if not line:
				continue
			if line[0] not in "UPMARD": # Updates,Patches,Modified,Added,Removed/Replaced(svn),Deleted(svn)
				logging.error(red("!!! Please fix the following issues reported " + \
					"from cvs: ")+green("(U,P,M,A,R,D are ok)"))
				logging.error(red("!!! Note: This is a pretend/no-modify pass..."))
				logging.error(retval[1])
				sys.exit(1)
			elif vcs == 'cvs' and line[0] in "UP":
				myupdates.append(line[2:])
			elif vcs == 'svn' and line[8] == '*':
				myupdates.append(line[9:].lstrip(" 1234567890"))

		if myupdates:
			logging.info(green("Fetching trivial updates..."))
			if options.pretend:
				logging.info("(" + vcs + " update " + " ".join(myupdates) + ")")
				retval = os.EX_OK
			else:
				retval = os.system(vcs + " update " + " ".join(myupdates))
			if retval != os.EX_OK:
				logging.fatal("!!! " + vcs + " exited with an error. Terminating.")
				sys.exit(retval)
Beispiel #7
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)
Beispiel #8
0
def get_commit_message_with_editor(editor, message=None):
    """
	Execute editor with a temporary file as it's argument
	and return the file content afterwards.

	@param editor: An EDITOR value from the environment
	@type: string
	@param message: An iterable of lines to show in the editor.
	@type: iterable
	@rtype: string or None
	@returns: A string on success or None if an error occurs.
	"""
    from tempfile import mkstemp
    fd, filename = mkstemp()
    try:
        os.write(fd, _unicode_encode(
         "\n# Please enter the commit message " + \
         "for your changes.\n# (Comment lines starting " + \
         "with '#' will not be included)\n",
         encoding=_encodings['content'], errors='backslashreplace'))
        if message:
            os.write(
                fd,
                _unicode_encode("#\n",
                                encoding=_encodings['content'],
                                errors='backslashreplace'))
            for line in message:
                os.write(
                    fd,
                    _unicode_encode("#" + line,
                                    encoding=_encodings['content'],
                                    errors='backslashreplace'))
        os.close(fd)
        retval = os.system(editor + " '%s'" % filename)
        if not (os.WIFEXITED(retval) and os.WEXITSTATUS(retval) == os.EX_OK):
            return None
        try:
            mylines = codecs.open(_unicode_encode(filename,
                                                  encoding=_encodings['fs'],
                                                  errors='strict'),
                                  mode='r',
                                  encoding=_encodings['content'],
                                  errors='replace').readlines()
        except OSError as e:
            if e.errno != errno.ENOENT:
                raise
            del e
            return None
        return "".join(line for line in mylines if not line.startswith("#"))
    finally:
        try:
            os.unlink(filename)
        except OSError:
            pass
Beispiel #9
0
def get_commit_message_with_editor(editor, message=None, prefix=""):
    """
	Execute editor with a temporary file as it's argument
	and return the file content afterwards.

	@param editor: An EDITOR value from the environment
	@type: string
	@param message: An iterable of lines to show in the editor.
	@type: iterable
	@param prefix: Suggested prefix for the commit message summary line.
	@type: string
	@rtype: string or None
	@return: A string on success or None if an error occurs.
	"""
    commitmessagedir = tempfile.mkdtemp(".repoman.msg")
    filename = os.path.join(commitmessagedir, "COMMIT_EDITMSG")
    try:
        with open(filename, "wb") as mymsg:
            mymsg.write(
                _unicode_encode(
                    _(prefix + "\n\n# Please enter the commit message "
                      "for your changes.\n# (Comment lines starting "
                      "with '#' will not be included)\n"),
                    encoding=_encodings['content'],
                    errors='backslashreplace'))
            if message:
                mymsg.write(b"#\n")
                for line in message:
                    mymsg.write(
                        _unicode_encode("#" + line,
                                        encoding=_encodings['content'],
                                        errors='backslashreplace'))
        retval = os.system(editor + " '%s'" % filename)
        if not (os.WIFEXITED(retval) and os.WEXITSTATUS(retval) == os.EX_OK):
            return None
        try:
            with io.open(_unicode_encode(filename,
                                         encoding=_encodings['fs'],
                                         errors='strict'),
                         mode='r',
                         encoding=_encodings['content'],
                         errors='replace') as f:
                mylines = f.readlines()
        except OSError as e:
            if e.errno != errno.ENOENT:
                raise
            del e
            return None
        return "".join(line for line in mylines if not line.startswith("#"))
    finally:
        try:
            shutil.rmtree(commitmessagedir)
        except OSError:
            pass
Beispiel #10
0
def file_archive(archive, curconf, newconf, mrgconf):
    """Archive existing config to the archive-dir, bumping old versions
	out of the way into .# versions (log-rotate style). Then, if mrgconf
	was specified and there is a .dist version, merge the user's changes
	and the distributed changes and put the result into mrgconf.  Lastly,
	if newconf was specified, archive it as a .dist.new version (which
	gets moved to the .dist version at the end of the processing)."""

    _file_archive_ensure_dir(os.path.dirname(archive))

    # Archive the current config file if it isn't already saved
    if (os.path.lexists(archive) and len(
            diffstatusoutput_mixed("diff -aq '%s' '%s'", curconf, archive)[1])
            != 0):
        _file_archive_rotate(archive)

    try:
        curconf_st = os.lstat(curconf)
    except OSError:
        curconf_st = None

    if curconf_st is not None and \
     (stat.S_ISREG(curconf_st.st_mode) or
     stat.S_ISLNK(curconf_st.st_mode)):
        _archive_copy(curconf_st, curconf, archive)

    mystat = None
    if newconf:
        try:
            mystat = os.lstat(newconf)
        except OSError:
            pass

    if mystat is not None and \
     (stat.S_ISREG(mystat.st_mode) or
     stat.S_ISLNK(mystat.st_mode)):
        # Save off new config file in the archive dir with .dist.new suffix
        newconf_archive = archive + '.dist.new'
        if os.path.isdir(
                newconf_archive) and not os.path.islink(newconf_archive):
            _file_archive_rotate(newconf_archive)
        _archive_copy(mystat, newconf, newconf_archive)

        ret = 0
        if mrgconf and os.path.isfile(curconf) and \
         os.path.isfile(newconf) and \
         os.path.isfile(archive + '.dist'):
            # This puts the results of the merge into mrgconf.
            ret = os.system(DIFF3_MERGE %
                            (curconf, archive + '.dist', newconf, mrgconf))
            os.chmod(mrgconf, mystat.st_mode)
            os.chown(mrgconf, mystat.st_uid, mystat.st_gid)

        return ret
Beispiel #11
0
def file_archive(archive, curconf, newconf, mrgconf):
	"""Archive existing config to the archive-dir, bumping old versions
	out of the way into .# versions (log-rotate style). Then, if mrgconf
	was specified and there is a .dist version, merge the user's changes
	and the distributed changes and put the result into mrgconf.  Lastly,
	if newconf was specified, archive it as a .dist.new version (which
	gets moved to the .dist version at the end of the processing)."""

	_file_archive_ensure_dir(os.path.dirname(archive))

	# Archive the current config file if it isn't already saved
	if (os.path.lexists(archive) and
		len(diffstatusoutput_mixed(
		"diff -aq '%s' '%s'", curconf, archive)[1]) != 0):
		_file_archive_rotate(archive)

	try:
		curconf_st = os.lstat(curconf)
	except OSError:
		curconf_st = None

	if curconf_st is not None and \
		(stat.S_ISREG(curconf_st.st_mode) or
		stat.S_ISLNK(curconf_st.st_mode)):
		_archive_copy(curconf_st, curconf, archive)

	mystat = None
	if newconf:
		try:
			mystat = os.lstat(newconf)
		except OSError:
			pass

	if mystat is not None and \
		(stat.S_ISREG(mystat.st_mode) or
		stat.S_ISLNK(mystat.st_mode)):
		# Save off new config file in the archive dir with .dist.new suffix
		newconf_archive = archive + '.dist.new'
		if os.path.isdir(newconf_archive
			) and not os.path.islink(newconf_archive):
			_file_archive_rotate(newconf_archive)
		_archive_copy(mystat, newconf, newconf_archive)

		ret = 0
		if mrgconf and os.path.isfile(curconf) and \
			os.path.isfile(newconf) and \
			os.path.isfile(archive + '.dist'):
			# This puts the results of the merge into mrgconf.
			ret = os.system(DIFF3_MERGE % (curconf, archive + '.dist', newconf, mrgconf))
			os.chmod(mrgconf, mystat.st_mode)
			os.chown(mrgconf, mystat.st_uid, mystat.st_gid)

		return ret
Beispiel #12
0
def get_commit_message_with_editor(editor, message=None):
    """
	Execute editor with a temporary file as it's argument
	and return the file content afterwards.

	@param editor: An EDITOR value from the environment
	@type: string
	@param message: An iterable of lines to show in the editor.
	@type: iterable
	@rtype: string or None
	@return: A string on success or None if an error occurs.
	"""
    fd, filename = mkstemp()
    try:
        os.write(
            fd,
            _unicode_encode(
                _(
                    "\n# Please enter the commit message "
                    + "for your changes.\n# (Comment lines starting "
                    + "with '#' will not be included)\n"
                ),
                encoding=_encodings["content"],
                errors="backslashreplace",
            ),
        )
        if message:
            os.write(fd, b"#\n")
            for line in message:
                os.write(fd, _unicode_encode("#" + line, encoding=_encodings["content"], errors="backslashreplace"))
        os.close(fd)
        retval = os.system(editor + " '%s'" % filename)
        if not (os.WIFEXITED(retval) and os.WEXITSTATUS(retval) == os.EX_OK):
            return None
        try:
            with io.open(
                _unicode_encode(filename, encoding=_encodings["fs"], errors="strict"),
                mode="r",
                encoding=_encodings["content"],
                errors="replace",
            ) as f:
                mylines = f.readlines()
        except OSError as e:
            if e.errno != errno.ENOENT:
                raise
            del e
            return None
        return "".join(line for line in mylines if not line.startswith("#"))
    finally:
        try:
            os.unlink(filename)
        except OSError:
            pass
Beispiel #13
0
def rcs_archive(archive, curconf, newconf, mrgconf):
	"""Archive existing config in rcs (on trunk). Then, if mrgconf is
	specified and an old branch version exists, merge the user's changes
	and the distributed changes and put the result into mrgconf.  Lastly,
	if newconf was specified, leave it in the archive dir with a .dist.new
	suffix along with the last 1.1.1 branch version with a .dist suffix."""

	try:
		os.makedirs(os.path.dirname(archive))
	except OSError:
		pass

	try:
		curconf_st = os.lstat(curconf)
	except OSError:
		curconf_st = None

	if curconf_st is not None and \
		(stat.S_ISREG(curconf_st.st_mode) or
		stat.S_ISLNK(curconf_st.st_mode)):
		_archive_copy(curconf_st, curconf, archive)

	if os.path.lexists(archive + ',v'):
		os.system(RCS_LOCK + ' ' + archive)
	os.system(RCS_PUT + ' ' + archive)

	ret = 0
	mystat = None
	if newconf:
		try:
			mystat = os.lstat(newconf)
		except OSError:
			pass

	if mystat is not None and \
		(stat.S_ISREG(mystat.st_mode) or
		stat.S_ISLNK(mystat.st_mode)):
		os.system(RCS_GET + ' -r' + RCS_BRANCH + ' ' + archive)
		has_branch = os.path.lexists(archive)
		if has_branch:
			os.rename(archive, archive + '.dist')

		_archive_copy(mystat, newconf, archive)

		if has_branch:
			if mrgconf and os.path.isfile(archive) and \
				os.path.isfile(mrgconf):
				# This puts the results of the merge into mrgconf.
				ret = os.system(RCS_MERGE % (archive, mrgconf))
				os.chmod(mrgconf, mystat.st_mode)
				os.chown(mrgconf, mystat.st_uid, mystat.st_gid)
		os.rename(archive, archive + '.dist.new')

	return ret
Beispiel #14
0
def rcs_archive(archive, curconf, newconf, mrgconf):
	"""Archive existing config in rcs (on trunk). Then, if mrgconf is
	specified and an old branch version exists, merge the user's changes
	and the distributed changes and put the result into mrgconf.  Lastly,
	if newconf was specified, leave it in the archive dir with a .dist.new
	suffix along with the last 1.1.1 branch version with a .dist suffix."""

	try:
		os.makedirs(os.path.dirname(archive))
	except OSError:
		pass

	try:
		curconf_st = os.lstat(curconf)
	except OSError:
		curconf_st = None

	if curconf_st is not None and \
		(stat.S_ISREG(curconf_st.st_mode) or
		stat.S_ISLNK(curconf_st.st_mode)):
		_archive_copy(curconf_st, curconf, archive)

	if os.path.lexists(archive + ',v'):
		os.system(RCS_LOCK + ' ' + archive)
	os.system(RCS_PUT + ' ' + archive)

	ret = 0
	mystat = None
	if newconf:
		try:
			mystat = os.lstat(newconf)
		except OSError:
			pass

	if mystat is not None and \
		(stat.S_ISREG(mystat.st_mode) or
		stat.S_ISLNK(mystat.st_mode)):
		os.system(RCS_GET + ' -r' + RCS_BRANCH + ' ' + archive)
		has_branch = os.path.lexists(archive)
		if has_branch:
			os.rename(archive, archive + '.dist')

		_archive_copy(mystat, newconf, archive)

		if has_branch:
			if mrgconf and os.path.isfile(archive) and \
				os.path.isfile(mrgconf):
				# This puts the results of the merge into mrgconf.
				ret = os.system(RCS_MERGE % (archive, mrgconf))
				os.chmod(mrgconf, mystat.st_mode)
				os.chown(mrgconf, mystat.st_uid, mystat.st_gid)
		os.rename(archive, archive + '.dist.new')

	return ret
Beispiel #15
0
def get_commit_message_with_editor(editor, message=None, prefix=""):
	"""
	Execute editor with a temporary file as it's argument
	and return the file content afterwards.

	@param editor: An EDITOR value from the environment
	@type: string
	@param message: An iterable of lines to show in the editor.
	@type: iterable
	@param prefix: Suggested prefix for the commit message summary line.
	@type: string
	@rtype: string or None
	@return: A string on success or None if an error occurs.
	"""
	commitmessagedir = tempfile.mkdtemp(".repoman.msg")
	filename = os.path.join(commitmessagedir, "COMMIT_EDITMSG")
	try:
		with open(filename, "wb") as mymsg:
			mymsg.write(
				_unicode_encode(_(
					prefix +
					"\n\n# Please enter the commit message "
					"for your changes.\n# (Comment lines starting "
					"with '#' will not be included)\n"),
					encoding=_encodings['content'], errors='backslashreplace'))
			if message:
				mymsg.write(b"#\n")
				for line in message:
					mymsg.write(
						_unicode_encode(
							"#" + line, encoding=_encodings['content'],
							errors='backslashreplace'))
		retval = os.system(editor + " '%s'" % filename)
		if not (os.WIFEXITED(retval) and os.WEXITSTATUS(retval) == os.EX_OK):
			return None
		try:
			with io.open(_unicode_encode(
				filename, encoding=_encodings['fs'], errors='strict'),
				mode='r', encoding=_encodings['content'], errors='replace') as f:
				mylines = f.readlines()
		except OSError as e:
			if e.errno != errno.ENOENT:
				raise
			del e
			return None
		return "".join(line for line in mylines if not line.startswith("#"))
	finally:
		try:
			shutil.rmtree(commitmessagedir)
		except OSError:
			pass
Beispiel #16
0
def rcs_archive_post_process(archive):
    """Check in the archive file with the .dist.new suffix on the branch
    and remove the one with the .dist suffix."""
    os.rename(archive + ".dist.new", archive)
    if os.path.lexists(archive + ".dist"):
        # Commit the last-distributed version onto the branch.
        os.system(RCS_LOCK + RCS_BRANCH + " " + archive)
        os.system(RCS_PUT + " -r" + RCS_BRANCH + " " + archive)
        os.unlink(archive + ".dist")
    else:
        # Forcefully commit the last-distributed version onto the branch.
        os.system(RCS_PUT + " -f -r" + RCS_BRANCH + " " + archive)
Beispiel #17
0
def rcs_archive_post_process(archive):
	"""Check in the archive file with the .dist.new suffix on the branch
	and remove the one with the .dist suffix."""
	os.rename(archive + '.dist.new', archive)
	if os.path.lexists(archive + '.dist'):
		# Commit the last-distributed version onto the branch.
		os.system(RCS_LOCK + RCS_BRANCH + ' ' + archive)
		os.system(RCS_PUT + ' -r' + RCS_BRANCH + ' ' + archive)
		os.unlink(archive + '.dist')
	else:
		# Forcefully commit the last-distributed version onto the branch.
		os.system(RCS_PUT + ' -f -r' + RCS_BRANCH + ' ' + archive)
Beispiel #18
0
def _env_update(makelinks, target_root, prev_mtimes, contents, env,
	writemsg_level):
	if writemsg_level is None:
		writemsg_level = portage.util.writemsg_level
	if target_root is None:
		target_root = portage.settings["ROOT"]
	if prev_mtimes is None:
		prev_mtimes = portage.mtimedb["ldpath"]
	if env is None:
		settings = portage.settings
	else:
		settings = env

	eprefix = settings.get("EPREFIX", "")
	eprefix_lstrip = eprefix.lstrip(os.sep)
	envd_dir = os.path.join(target_root, eprefix_lstrip, "etc", "env.d")
	ensure_dirs(envd_dir, mode=0o755)
	fns = listdir(envd_dir, EmptyOnError=1)
	fns.sort()
	templist = []
	for x in fns:
		if len(x) < 3:
			continue
		if not x[0].isdigit() or not x[1].isdigit():
			continue
		if x.startswith(".") or x.endswith("~") or x.endswith(".bak"):
			continue
		templist.append(x)
	fns = templist
	del templist

	space_separated = set(["CONFIG_PROTECT", "CONFIG_PROTECT_MASK"])
	colon_separated = set(["ADA_INCLUDE_PATH", "ADA_OBJECTS_PATH",
		"CLASSPATH", "INFODIR", "INFOPATH", "KDEDIRS", "LDPATH", "MANPATH",
		  "PATH", "PKG_CONFIG_PATH", "PRELINK_PATH", "PRELINK_PATH_MASK",
		  "PYTHONPATH", "ROOTPATH"])

	config_list = []

	for x in fns:
		file_path = os.path.join(envd_dir, x)
		try:
			myconfig = getconfig(file_path, expand=False)
		except ParseError as e:
			writemsg("!!! '%s'\n" % str(e), noiselevel=-1)
			del e
			continue
		if myconfig is None:
			# broken symlink or file removed by a concurrent process
			writemsg("!!! File Not Found: '%s'\n" % file_path, noiselevel=-1)
			continue

		config_list.append(myconfig)
		if "SPACE_SEPARATED" in myconfig:
			space_separated.update(myconfig["SPACE_SEPARATED"].split())
			del myconfig["SPACE_SEPARATED"]
		if "COLON_SEPARATED" in myconfig:
			colon_separated.update(myconfig["COLON_SEPARATED"].split())
			del myconfig["COLON_SEPARATED"]

	env = {}
	specials = {}
	for var in space_separated:
		mylist = []
		for myconfig in config_list:
			if var in myconfig:
				for item in myconfig[var].split():
					if item and not item in mylist:
						mylist.append(item)
				del myconfig[var] # prepare for env.update(myconfig)
		if mylist:
			env[var] = " ".join(mylist)
		specials[var] = mylist

	for var in colon_separated:
		mylist = []
		for myconfig in config_list:
			if var in myconfig:
				for item in myconfig[var].split(":"):
					if item and not item in mylist:
						mylist.append(item)
				del myconfig[var] # prepare for env.update(myconfig)
		if mylist:
			env[var] = ":".join(mylist)
		specials[var] = mylist

	for myconfig in config_list:
		"""Cumulative variables have already been deleted from myconfig so that
		they won't be overwritten by this dict.update call."""
		env.update(myconfig)

	ldsoconf_path = os.path.join(
		target_root, eprefix_lstrip, "etc", "ld.so.conf")
	try:
		myld = io.open(_unicode_encode(ldsoconf_path,
			encoding=_encodings['fs'], errors='strict'),
			mode='r', encoding=_encodings['content'], errors='replace')
		myldlines=myld.readlines()
		myld.close()
		oldld=[]
		for x in myldlines:
			#each line has at least one char (a newline)
			if x[:1] == "#":
				continue
			oldld.append(x[:-1])
	except (IOError, OSError) as e:
		if e.errno != errno.ENOENT:
			raise
		oldld = None

	newld = specials["LDPATH"]
	if (oldld != newld):
		#ld.so.conf needs updating and ldconfig needs to be run
		myfd = atomic_ofstream(ldsoconf_path)
		myfd.write("# ld.so.conf autogenerated by env-update; make all changes to\n")
		myfd.write("# contents of /etc/env.d directory\n")
		for x in specials["LDPATH"]:
			myfd.write(x + "\n")
		myfd.close()

	# Update prelink.conf if we are prelink-enabled
	if prelink_capable:
		newprelink = atomic_ofstream(os.path.join(
			target_root, eprefix_lstrip, "etc", "prelink.conf"))
		newprelink.write("# prelink.conf autogenerated by env-update; make all changes to\n")
		newprelink.write("# contents of /etc/env.d directory\n")

		for x in ["/bin","/sbin","/usr/bin","/usr/sbin","/lib","/usr/lib"]:
			newprelink.write("-l %s\n" % (x,));
		prelink_paths = []
		prelink_paths += specials.get("LDPATH", [])
		prelink_paths += specials.get("PATH", [])
		prelink_paths += specials.get("PRELINK_PATH", [])
		prelink_path_mask = specials.get("PRELINK_PATH_MASK", [])
		for x in prelink_paths:
			if not x:
				continue
			if x[-1:] != '/':
				x += "/"
			plmasked = 0
			for y in prelink_path_mask:
				if not y:
					continue
				if y[-1] != '/':
					y += "/"
				if y == x[0:len(y)]:
					plmasked = 1
					break
			if not plmasked:
				newprelink.write("-h %s\n" % (x,))
		for x in prelink_path_mask:
			newprelink.write("-b %s\n" % (x,))
		newprelink.close()

	current_time = long(time.time())
	mtime_changed = False
	lib_dirs = set()
	for lib_dir in set(specials["LDPATH"] + \
		['usr/lib','usr/lib64','usr/lib32','lib','lib64','lib32']):
		x = os.path.join(target_root, eprefix_lstrip, lib_dir.lstrip(os.sep))
		try:
			newldpathtime = os.stat(x)[stat.ST_MTIME]
			lib_dirs.add(normalize_path(x))
		except OSError as oe:
			if oe.errno == errno.ENOENT:
				try:
					del prev_mtimes[x]
				except KeyError:
					pass
				# ignore this path because it doesn't exist
				continue
			raise
		if newldpathtime == current_time:
			# Reset mtime to avoid the potential ambiguity of times that
			# differ by less than 1 second.
			newldpathtime -= 1
			os.utime(x, (newldpathtime, newldpathtime))
			prev_mtimes[x] = newldpathtime
			mtime_changed = True
		elif x in prev_mtimes:
			if prev_mtimes[x] == newldpathtime:
				pass
			else:
				prev_mtimes[x] = newldpathtime
				mtime_changed = True
		else:
			prev_mtimes[x] = newldpathtime
			mtime_changed = True

	if makelinks and \
		not mtime_changed and \
		contents is not None:
		libdir_contents_changed = False
		for mypath, mydata in contents.items():
			if mydata[0] not in ("obj", "sym"):
				continue
			head, tail = os.path.split(mypath)
			if head in lib_dirs:
				libdir_contents_changed = True
				break
		if not libdir_contents_changed:
			makelinks = False

	ldconfig = "/sbin/ldconfig"
	if "CHOST" in settings and "CBUILD" in settings and \
		settings["CHOST"] != settings["CBUILD"]:
		ldconfig = find_binary("%s-ldconfig" % settings["CHOST"])

	# Only run ldconfig as needed
	if makelinks and ldconfig and not eprefix:
		# ldconfig has very different behaviour between FreeBSD and Linux
		if ostype == "Linux" or ostype.lower().endswith("gnu"):
			# We can't update links if we haven't cleaned other versions first, as
			# an older package installed ON TOP of a newer version will cause ldconfig
			# to overwrite the symlinks we just made. -X means no links. After 'clean'
			# we can safely create links.
			writemsg_level(_(">>> Regenerating %setc/ld.so.cache...\n") % \
				(target_root,))
			os.system("cd / ; %s -X -r '%s'" % (ldconfig, target_root))
		elif ostype in ("FreeBSD","DragonFly"):
			writemsg_level(_(">>> Regenerating %svar/run/ld-elf.so.hints...\n") % \
				target_root)
			os.system(("cd / ; %s -elf -i " + \
				"-f '%svar/run/ld-elf.so.hints' '%setc/ld.so.conf'") % \
				(ldconfig, target_root, target_root))

	del specials["LDPATH"]

	penvnotice  = "# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.\n"
	penvnotice += "# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES\n"
	cenvnotice  = penvnotice[:]
	penvnotice += "# GO INTO /etc/profile NOT /etc/profile.env\n\n"
	cenvnotice += "# GO INTO /etc/csh.cshrc NOT /etc/csh.env\n\n"

	#create /etc/profile.env for bash support
	outfile = atomic_ofstream(os.path.join(
		target_root, eprefix_lstrip, "etc", "profile.env"))
	outfile.write(penvnotice)

	env_keys = [ x for x in env if x != "LDPATH" ]
	env_keys.sort()
	for k in env_keys:
		v = env[k]
		if v.startswith('$') and not v.startswith('${'):
			outfile.write("export %s=$'%s'\n" % (k, v[1:]))
		else:
			outfile.write("export %s='%s'\n" % (k, v))
	outfile.close()

	#create /etc/csh.env for (t)csh support
	outfile = atomic_ofstream(os.path.join(
		target_root, eprefix_lstrip, "etc", "csh.env"))
	outfile.write(cenvnotice)
	for x in env_keys:
		outfile.write("setenv %s '%s'\n" % (x, env[x]))
	outfile.close()
def _env_update(makelinks, target_root, prev_mtimes, contents, env,
                writemsg_level):
    if writemsg_level is None:
        writemsg_level = portage.util.writemsg_level
    if target_root is None:
        target_root = portage.settings["ROOT"]
    if prev_mtimes is None:
        prev_mtimes = portage.mtimedb["ldpath"]
    if env is None:
        settings = portage.settings
    else:
        settings = env

    eprefix = settings.get("EPREFIX", "")
    eprefix_lstrip = eprefix.lstrip(os.sep)
    eroot = normalize_path(os.path.join(target_root, eprefix_lstrip)).rstrip(
        os.sep) + os.sep
    envd_dir = os.path.join(eroot, "etc", "env.d")
    ensure_dirs(envd_dir, mode=0o755)
    fns = listdir(envd_dir, EmptyOnError=1)
    fns.sort()
    templist = []
    for x in fns:
        if len(x) < 3:
            continue
        if not x[0].isdigit() or not x[1].isdigit():
            continue
        if x.startswith(".") or x.endswith("~") or x.endswith(".bak"):
            continue
        templist.append(x)
    fns = templist
    del templist

    space_separated = set(["CONFIG_PROTECT", "CONFIG_PROTECT_MASK"])
    colon_separated = set([
        "ADA_INCLUDE_PATH", "ADA_OBJECTS_PATH", "CLASSPATH", "INFODIR",
        "INFOPATH", "KDEDIRS", "LDPATH", "MANPATH", "PATH", "PKG_CONFIG_PATH",
        "PRELINK_PATH", "PRELINK_PATH_MASK", "PYTHONPATH", "ROOTPATH"
    ])

    config_list = []

    for x in fns:
        file_path = os.path.join(envd_dir, x)
        try:
            myconfig = getconfig(file_path, expand=False)
        except ParseError as e:
            writemsg("!!! '%s'\n" % str(e), noiselevel=-1)
            del e
            continue
        if myconfig is None:
            # broken symlink or file removed by a concurrent process
            writemsg("!!! File Not Found: '%s'\n" % file_path, noiselevel=-1)
            continue

        config_list.append(myconfig)
        if "SPACE_SEPARATED" in myconfig:
            space_separated.update(myconfig["SPACE_SEPARATED"].split())
            del myconfig["SPACE_SEPARATED"]
        if "COLON_SEPARATED" in myconfig:
            colon_separated.update(myconfig["COLON_SEPARATED"].split())
            del myconfig["COLON_SEPARATED"]

    env = {}
    specials = {}
    for var in space_separated:
        mylist = []
        for myconfig in config_list:
            if var in myconfig:
                for item in myconfig[var].split():
                    if item and not item in mylist:
                        mylist.append(item)
                del myconfig[var]  # prepare for env.update(myconfig)
        if mylist:
            env[var] = " ".join(mylist)
        specials[var] = mylist

    for var in colon_separated:
        mylist = []
        for myconfig in config_list:
            if var in myconfig:
                for item in myconfig[var].split(":"):
                    if item and not item in mylist:
                        mylist.append(item)
                del myconfig[var]  # prepare for env.update(myconfig)
        if mylist:
            env[var] = ":".join(mylist)
        specials[var] = mylist

    for myconfig in config_list:
        """Cumulative variables have already been deleted from myconfig so that
		they won't be overwritten by this dict.update call."""
        env.update(myconfig)

    ldsoconf_path = os.path.join(eroot, "etc", "ld.so.conf")
    try:
        myld = io.open(_unicode_encode(ldsoconf_path,
                                       encoding=_encodings['fs'],
                                       errors='strict'),
                       mode='r',
                       encoding=_encodings['content'],
                       errors='replace')
        myldlines = myld.readlines()
        myld.close()
        oldld = []
        for x in myldlines:
            #each line has at least one char (a newline)
            if x[:1] == "#":
                continue
            oldld.append(x[:-1])
    except (IOError, OSError) as e:
        if e.errno != errno.ENOENT:
            raise
        oldld = None

    newld = specials["LDPATH"]
    if (oldld != newld):
        #ld.so.conf needs updating and ldconfig needs to be run
        myfd = atomic_ofstream(ldsoconf_path)
        myfd.write(
            "# ld.so.conf autogenerated by env-update; make all changes to\n")
        myfd.write("# contents of /etc/env.d directory\n")
        for x in specials["LDPATH"]:
            myfd.write(x + "\n")
        myfd.close()

    potential_lib_dirs = set()
    for lib_dir_glob in ('usr/lib*', 'lib*'):
        x = os.path.join(eroot, lib_dir_glob)
        for y in glob.glob(
                _unicode_encode(x, encoding=_encodings['fs'],
                                errors='strict')):
            try:
                y = _unicode_decode(y,
                                    encoding=_encodings['fs'],
                                    errors='strict')
            except UnicodeDecodeError:
                continue
            if os.path.basename(y) != 'libexec':
                potential_lib_dirs.add(y[len(eroot):])

    # Update prelink.conf if we are prelink-enabled
    if prelink_capable:
        prelink_d = os.path.join(eroot, 'etc', 'prelink.conf.d')
        ensure_dirs(prelink_d)
        newprelink = atomic_ofstream(os.path.join(prelink_d, 'portage.conf'))
        newprelink.write(
            "# prelink.conf autogenerated by env-update; make all changes to\n"
        )
        newprelink.write("# contents of /etc/env.d directory\n")

        for x in sorted(potential_lib_dirs) + ['bin', 'sbin']:
            newprelink.write('-l /%s\n' % (x, ))
        prelink_paths = set()
        prelink_paths |= set(specials.get('LDPATH', []))
        prelink_paths |= set(specials.get('PATH', []))
        prelink_paths |= set(specials.get('PRELINK_PATH', []))
        prelink_path_mask = specials.get('PRELINK_PATH_MASK', [])
        for x in prelink_paths:
            if not x:
                continue
            if x[-1:] != '/':
                x += "/"
            plmasked = 0
            for y in prelink_path_mask:
                if not y:
                    continue
                if y[-1] != '/':
                    y += "/"
                if y == x[0:len(y)]:
                    plmasked = 1
                    break
            if not plmasked:
                newprelink.write("-h %s\n" % (x, ))
        for x in prelink_path_mask:
            newprelink.write("-b %s\n" % (x, ))
        newprelink.close()

        # Migration code path.  If /etc/prelink.conf was generated by us, then
        # point it to the new stuff until the prelink package re-installs.
        prelink_conf = os.path.join(eroot, 'etc', 'prelink.conf')
        try:
            with open(
                    _unicode_encode(prelink_conf,
                                    encoding=_encodings['fs'],
                                    errors='strict'), 'rb') as f:
                if f.readline(
                ) == b'# prelink.conf autogenerated by env-update; make all changes to\n':
                    f = atomic_ofstream(prelink_conf)
                    f.write('-c /etc/prelink.conf.d/*.conf\n')
                    f.close()
        except IOError as e:
            if e.errno != errno.ENOENT:
                raise

    current_time = long(time.time())
    mtime_changed = False

    lib_dirs = set()
    for lib_dir in set(specials['LDPATH']) | potential_lib_dirs:
        x = os.path.join(eroot, lib_dir.lstrip(os.sep))
        try:
            newldpathtime = os.stat(x)[stat.ST_MTIME]
            lib_dirs.add(normalize_path(x))
        except OSError as oe:
            if oe.errno == errno.ENOENT:
                try:
                    del prev_mtimes[x]
                except KeyError:
                    pass
                # ignore this path because it doesn't exist
                continue
            raise
        if newldpathtime == current_time:
            # Reset mtime to avoid the potential ambiguity of times that
            # differ by less than 1 second.
            newldpathtime -= 1
            os.utime(x, (newldpathtime, newldpathtime))
            prev_mtimes[x] = newldpathtime
            mtime_changed = True
        elif x in prev_mtimes:
            if prev_mtimes[x] == newldpathtime:
                pass
            else:
                prev_mtimes[x] = newldpathtime
                mtime_changed = True
        else:
            prev_mtimes[x] = newldpathtime
            mtime_changed = True

    if makelinks and \
     not mtime_changed and \
     contents is not None:
        libdir_contents_changed = False
        for mypath, mydata in contents.items():
            if mydata[0] not in ("obj", "sym"):
                continue
            head, tail = os.path.split(mypath)
            if head in lib_dirs:
                libdir_contents_changed = True
                break
        if not libdir_contents_changed:
            makelinks = False

    ldconfig = "/sbin/ldconfig"
    if "CHOST" in settings and "CBUILD" in settings and \
     settings["CHOST"] != settings["CBUILD"]:
        ldconfig = find_binary("%s-ldconfig" % settings["CHOST"])

    # Only run ldconfig as needed
    if makelinks and ldconfig and not eprefix:
        # ldconfig has very different behaviour between FreeBSD and Linux
        if ostype == "Linux" or ostype.lower().endswith("gnu"):
            # We can't update links if we haven't cleaned other versions first, as
            # an older package installed ON TOP of a newer version will cause ldconfig
            # to overwrite the symlinks we just made. -X means no links. After 'clean'
            # we can safely create links.
            writemsg_level(_(">>> Regenerating %setc/ld.so.cache...\n") % \
             (target_root,))
            os.system("cd / ; %s -X -r '%s'" % (ldconfig, target_root))
        elif ostype in ("FreeBSD", "DragonFly"):
            writemsg_level(_(">>> Regenerating %svar/run/ld-elf.so.hints...\n") % \
             target_root)
            os.system(("cd / ; %s -elf -i " + \
             "-f '%svar/run/ld-elf.so.hints' '%setc/ld.so.conf'") % \
             (ldconfig, target_root, target_root))

    del specials["LDPATH"]

    penvnotice = "# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.\n"
    penvnotice += "# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES\n"
    cenvnotice = penvnotice[:]
    penvnotice += "# GO INTO /etc/profile NOT /etc/profile.env\n\n"
    cenvnotice += "# GO INTO /etc/csh.cshrc NOT /etc/csh.env\n\n"

    #create /etc/profile.env for bash support
    outfile = atomic_ofstream(os.path.join(eroot, "etc", "profile.env"))
    outfile.write(penvnotice)

    env_keys = [x for x in env if x != "LDPATH"]
    env_keys.sort()
    for k in env_keys:
        v = env[k]
        if v.startswith('$') and not v.startswith('${'):
            outfile.write("export %s=$'%s'\n" % (k, v[1:]))
        else:
            outfile.write("export %s='%s'\n" % (k, v))
    outfile.close()

    #create /etc/csh.env for (t)csh support
    outfile = atomic_ofstream(os.path.join(eroot, "etc", "csh.env"))
    outfile.write(cenvnotice)
    for x in env_keys:
        outfile.write("setenv %s '%s'\n" % (x, env[x]))
    outfile.close()
Beispiel #20
0
def env_update(makelinks=1, target_root=None, prev_mtimes=None, contents=None,
	env=None, writemsg_level=None):
	"""
	Parse /etc/env.d and use it to generate /etc/profile.env, csh.env,
	ld.so.conf, and prelink.conf. Finally, run ldconfig.
	"""
	if writemsg_level is None:
		writemsg_level = portage.util.writemsg_level
	if target_root is None:
		target_root = portage.settings["ROOT"]
	if prev_mtimes is None:
		prev_mtimes = portage.mtimedb["ldpath"]
	if env is None:
		env = os.environ
	envd_dir = os.path.join(target_root, "etc", "env.d")
	ensure_dirs(envd_dir, mode=0o755)
	fns = listdir(envd_dir, EmptyOnError=1)
	fns.sort()
	templist = []
	for x in fns:
		if len(x) < 3:
			continue
		if not x[0].isdigit() or not x[1].isdigit():
			continue
		if x.startswith(".") or x.endswith("~") or x.endswith(".bak"):
			continue
		templist.append(x)
	fns = templist
	del templist

	space_separated = set(["CONFIG_PROTECT", "CONFIG_PROTECT_MASK"])
	colon_separated = set(["ADA_INCLUDE_PATH", "ADA_OBJECTS_PATH",
		"CLASSPATH", "INFODIR", "INFOPATH", "KDEDIRS", "LDPATH", "MANPATH",
		  "PATH", "PKG_CONFIG_PATH", "PRELINK_PATH", "PRELINK_PATH_MASK",
		  "PYTHONPATH", "ROOTPATH"])

	config_list = []

	for x in fns:
		file_path = os.path.join(envd_dir, x)
		try:
			myconfig = getconfig(file_path, expand=False)
		except ParseError as e:
			writemsg("!!! '%s'\n" % str(e), noiselevel=-1)
			del e
			continue
		if myconfig is None:
			# broken symlink or file removed by a concurrent process
			writemsg("!!! File Not Found: '%s'\n" % file_path, noiselevel=-1)
			continue

		config_list.append(myconfig)
		if "SPACE_SEPARATED" in myconfig:
			space_separated.update(myconfig["SPACE_SEPARATED"].split())
			del myconfig["SPACE_SEPARATED"]
		if "COLON_SEPARATED" in myconfig:
			colon_separated.update(myconfig["COLON_SEPARATED"].split())
			del myconfig["COLON_SEPARATED"]

	env = {}
	specials = {}
	for var in space_separated:
		mylist = []
		for myconfig in config_list:
			if var in myconfig:
				for item in myconfig[var].split():
					if item and not item in mylist:
						mylist.append(item)
				del myconfig[var] # prepare for env.update(myconfig)
		if mylist:
			env[var] = " ".join(mylist)
		specials[var] = mylist

	for var in colon_separated:
		mylist = []
		for myconfig in config_list:
			if var in myconfig:
				for item in myconfig[var].split(":"):
					if item and not item in mylist:
						mylist.append(item)
				del myconfig[var] # prepare for env.update(myconfig)
		if mylist:
			env[var] = ":".join(mylist)
		specials[var] = mylist

	for myconfig in config_list:
		"""Cumulative variables have already been deleted from myconfig so that
		they won't be overwritten by this dict.update call."""
		env.update(myconfig)

	ldsoconf_path = os.path.join(target_root, "etc", "ld.so.conf")
	try:
		myld = codecs.open(_unicode_encode(ldsoconf_path,
			encoding=_encodings['fs'], errors='strict'),
			mode='r', encoding=_encodings['content'], errors='replace')
		myldlines=myld.readlines()
		myld.close()
		oldld=[]
		for x in myldlines:
			#each line has at least one char (a newline)
			if x[:1] == "#":
				continue
			oldld.append(x[:-1])
	except (IOError, OSError) as e:
		if e.errno != errno.ENOENT:
			raise
		oldld = None

	ld_cache_update=False

	newld = specials["LDPATH"]
	if (oldld != newld):
		#ld.so.conf needs updating and ldconfig needs to be run
		myfd = atomic_ofstream(ldsoconf_path)
		myfd.write("# ld.so.conf autogenerated by env-update; make all changes to\n")
		myfd.write("# contents of /etc/env.d directory\n")
		for x in specials["LDPATH"]:
			myfd.write(x + "\n")
		myfd.close()
		ld_cache_update=True

	# Update prelink.conf if we are prelink-enabled
	if prelink_capable:
		newprelink = atomic_ofstream(
			os.path.join(target_root, "etc", "prelink.conf"))
		newprelink.write("# prelink.conf autogenerated by env-update; make all changes to\n")
		newprelink.write("# contents of /etc/env.d directory\n")

		for x in ["/bin","/sbin","/usr/bin","/usr/sbin","/lib","/usr/lib"]:
			newprelink.write("-l %s\n" % (x,));
		prelink_paths = []
		prelink_paths += specials.get("LDPATH", [])
		prelink_paths += specials.get("PATH", [])
		prelink_paths += specials.get("PRELINK_PATH", [])
		prelink_path_mask = specials.get("PRELINK_PATH_MASK", [])
		for x in prelink_paths:
			if not x:
				continue
			if x[-1:] != '/':
				x += "/"
			plmasked = 0
			for y in prelink_path_mask:
				if not y:
					continue
				if y[-1] != '/':
					y += "/"
				if y == x[0:len(y)]:
					plmasked = 1
					break
			if not plmasked:
				newprelink.write("-h %s\n" % (x,))
		for x in prelink_path_mask:
			newprelink.write("-b %s\n" % (x,))
		newprelink.close()

	# Portage stores mtimes with 1 second granularity but in >=python-2.5 finer
	# granularity is possible.  In order to avoid the potential ambiguity of
	# mtimes that differ by less than 1 second, sleep here if any of the
	# directories have been modified during the current second.
	sleep_for_mtime_granularity = False
	current_time = long(time.time())
	mtime_changed = False
	lib_dirs = set()
	for lib_dir in set(specials["LDPATH"] + \
		['usr/lib','usr/lib64','usr/lib32','lib','lib64','lib32']):
		x = os.path.join(target_root, lib_dir.lstrip(os.sep))
		try:
			newldpathtime = os.stat(x)[stat.ST_MTIME]
			lib_dirs.add(normalize_path(x))
		except OSError as oe:
			if oe.errno == errno.ENOENT:
				try:
					del prev_mtimes[x]
				except KeyError:
					pass
				# ignore this path because it doesn't exist
				continue
			raise
		if newldpathtime == current_time:
			sleep_for_mtime_granularity = True
		if x in prev_mtimes:
			if prev_mtimes[x] == newldpathtime:
				pass
			else:
				prev_mtimes[x] = newldpathtime
				mtime_changed = True
		else:
			prev_mtimes[x] = newldpathtime
			mtime_changed = True

	if mtime_changed:
		ld_cache_update = True

	if makelinks and \
		not ld_cache_update and \
		contents is not None:
		libdir_contents_changed = False
		for mypath, mydata in contents.items():
			if mydata[0] not in ("obj", "sym"):
				continue
			head, tail = os.path.split(mypath)
			if head in lib_dirs:
				libdir_contents_changed = True
				break
		if not libdir_contents_changed:
			makelinks = False

	ldconfig = "/sbin/ldconfig"
	if "CHOST" in env and "CBUILD" in env and \
		env["CHOST"] != env["CBUILD"]:
		ldconfig = find_binary("%s-ldconfig" % env["CHOST"])

	# Only run ldconfig as needed
	if (ld_cache_update or makelinks) and ldconfig:
		# ldconfig has very different behaviour between FreeBSD and Linux
		if ostype == "Linux" or ostype.lower().endswith("gnu"):
			# We can't update links if we haven't cleaned other versions first, as
			# an older package installed ON TOP of a newer version will cause ldconfig
			# to overwrite the symlinks we just made. -X means no links. After 'clean'
			# we can safely create links.
			writemsg_level(_(">>> Regenerating %setc/ld.so.cache...\n") % \
				(target_root,))
			if makelinks:
				os.system("cd / ; %s -r '%s'" % (ldconfig, target_root))
			else:
				os.system("cd / ; %s -X -r '%s'" % (ldconfig, target_root))
		elif ostype in ("FreeBSD","DragonFly"):
			writemsg_level(_(">>> Regenerating %svar/run/ld-elf.so.hints...\n") % \
				target_root)
			os.system(("cd / ; %s -elf -i " + \
				"-f '%svar/run/ld-elf.so.hints' '%setc/ld.so.conf'") % \
				(ldconfig, target_root, target_root))

	del specials["LDPATH"]

	penvnotice  = "# THIS FILE IS AUTOMATICALLY GENERATED BY env-update.\n"
	penvnotice += "# DO NOT EDIT THIS FILE. CHANGES TO STARTUP PROFILES\n"
	cenvnotice  = penvnotice[:]
	penvnotice += "# GO INTO /etc/profile NOT /etc/profile.env\n\n"
	cenvnotice += "# GO INTO /etc/csh.cshrc NOT /etc/csh.env\n\n"

	#create /etc/profile.env for bash support
	outfile = atomic_ofstream(os.path.join(target_root, "etc", "profile.env"))
	outfile.write(penvnotice)

	env_keys = [ x for x in env if x != "LDPATH" ]
	env_keys.sort()
	for k in env_keys:
		v = env[k]
		if v.startswith('$') and not v.startswith('${'):
			outfile.write("export %s=$'%s'\n" % (k, v[1:]))
		else:
			outfile.write("export %s='%s'\n" % (k, v))
	outfile.close()

	#create /etc/csh.env for (t)csh support
	outfile = atomic_ofstream(os.path.join(target_root, "etc", "csh.env"))
	outfile.write(cenvnotice)
	for x in env_keys:
		outfile.write("setenv %s '%s'\n" % (x, env[x]))
	outfile.close()

	if sleep_for_mtime_granularity:
		while current_time == long(time.time()):
			time.sleep(1)
Beispiel #21
0
    def detect_conflicts(options):
        """Determine if the checkout has problems like cvs conflicts.

		If you want more vcs support here just keep adding if blocks...
		This could be better.

		TODO(antarus): Also this should probably not call sys.exit() as
		repoman is run on >1 packages and one failure should not cause
		subsequent packages to fail.

		Args:
			vcs - A string identifying the version control system in use
		Returns: boolean
			(calls sys.exit on fatal problems)
		"""

        cmd = "svn status -u 2>&1 | egrep -v '^.  +.*/digest-[^/]+' | head -n-1"
        msg = (
            "Performing a %s with a little magic grep to check for updates." %
            green("svn status -u"))

        logging.info(msg)
        # Use Popen instead of getstatusoutput(), in order to avoid
        # unicode handling problems (see bug #310789).
        args = [BASH_BINARY, "-c", cmd]
        args = [_unicode_encode(x) for x in args]
        proc = subprocess.Popen(args,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT)
        out = _unicode_decode(proc.communicate()[0])
        proc.wait()
        mylines = out.splitlines()
        myupdates = []
        for line in mylines:
            if not line:
                continue

            # [ ] Unmodified (SVN)	[U] Updates		[P] Patches
            # [M] Modified			[A] Added		[R] Removed / Replaced
            # [D] Deleted
            if line[0] not in " UPMARD":
                # Stray Manifest is fine, we will readd it anyway.
                if line[0] == '?' and line[1:].lstrip() == 'Manifest':
                    continue
                logging.error(
                    red("!!! Please fix the following issues reported "
                        "from cvs: %s" % green("(U,P,M,A,R,D are ok)")))
                logging.error(
                    red("!!! Note: This is a pretend/no-modify pass..."))
                logging.error(out)
                sys.exit(1)
            elif line[8] == '*':
                myupdates.append(line[9:].lstrip(" 1234567890"))

        if myupdates:
            logging.info(green("Fetching trivial updates..."))
            if options.pretend:
                logging.info("(svn update " + " ".join(myupdates) + ")")
                retval = os.EX_OK
            else:
                retval = os.system("svn update " + " ".join(myupdates))
            if retval != os.EX_OK:
                logging.fatal("!!! svn exited with an error. Terminating.")
                sys.exit(retval)
        return False
Beispiel #22
0
def detect_vcs_conflicts(options, vcs):
    """Determine if the checkout has problems like cvs conflicts.
	
	If you want more vcs support here just keep adding if blocks...
	This could be better.
	
	TODO(antarus): Also this should probably not call sys.exit() as
	repoman is run on >1 packages and one failure should not cause
	subsequent packages to fail.
	
	Args:
		vcs - A string identifying the version control system in use
	Returns:
		None (calls sys.exit on fatal problems)
	"""

    cmd = None
    if vcs == 'cvs':
        logging.info("Performing a " + output.green("cvs -n up") + \
         " with a little magic grep to check for updates.")
        cmd = "cvs -n up 2>/dev/null | " + \
         "egrep '^[^\?] .*' | " + \
         "egrep -v '^. .*/digest-[^/]+|^cvs server: .* -- ignored$'"
    if vcs == 'svn':
        logging.info("Performing a " + output.green("svn status -u") + \
         " with a little magic grep to check for updates.")
        cmd = "svn status -u 2>&1 | " + \
         "egrep -v '^.  +.*/digest-[^/]+' | " + \
         "head -n-1"

    if cmd is not None:
        # Use Popen instead of getstatusoutput(), in order to avoid
        # unicode handling problems (see bug #310789).
        args = [BASH_BINARY, "-c", cmd]
        if sys.hexversion < 0x3000000 or sys.hexversion >= 0x3020000:
            # Python 3.1 does not support bytes in Popen args.
            args = [_unicode_encode(x) for x in args]
        proc = subprocess.Popen(args,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT)
        out = _unicode_decode(proc.communicate()[0])
        proc.wait()
        mylines = out.splitlines()
        myupdates = []
        for line in mylines:
            if not line:
                continue
            if line[0] not in " UPMARD":  # unmodified(svn),Updates,Patches,Modified,Added,Removed/Replaced(svn),Deleted(svn)
                # Stray Manifest is fine, we will readd it anyway.
                if line[0] == '?' and line[1:].lstrip() == 'Manifest':
                    continue
                logging.error(red("!!! Please fix the following issues reported " + \
                 "from cvs: ")+green("(U,P,M,A,R,D are ok)"))
                logging.error(
                    red("!!! Note: This is a pretend/no-modify pass..."))
                logging.error(out)
                sys.exit(1)
            elif vcs == 'cvs' and line[0] in "UP":
                myupdates.append(line[2:])
            elif vcs == 'svn' and line[8] == '*':
                myupdates.append(line[9:].lstrip(" 1234567890"))

        if myupdates:
            logging.info(green("Fetching trivial updates..."))
            if options.pretend:
                logging.info("(" + vcs + " update " + " ".join(myupdates) +
                             ")")
                retval = os.EX_OK
            else:
                retval = os.system(vcs + " update " + " ".join(myupdates))
            if retval != os.EX_OK:
                logging.fatal("!!! " + vcs +
                              " exited with an error. Terminating.")
                sys.exit(retval)
Beispiel #23
0
def detect_vcs_conflicts(options, vcs):
    """Determine if the checkout has problems like cvs conflicts.
	
	If you want more vcs support here just keep adding if blocks...
	This could be better.
	
	TODO(antarus): Also this should probably not call sys.exit() as
	repoman is run on >1 packages and one failure should not cause
	subsequent packages to fail.
	
	Args:
		vcs - A string identifying the version control system in use
	Returns:
		None (calls sys.exit on fatal problems)
	"""

    cmd = None
    if vcs == "cvs":
        logging.info("Performing a " + output.green("cvs -n up") + " with a little magic grep to check for updates.")
        cmd = (
            "cvs -n up 2>/dev/null | "
            + "egrep '^[^\?] .*' | "
            + "egrep -v '^. .*/digest-[^/]+|^cvs server: .* -- ignored$'"
        )
    if vcs == "svn":
        logging.info(
            "Performing a " + output.green("svn status -u") + " with a little magic grep to check for updates."
        )
        cmd = "svn status -u 2>&1 | " + "egrep -v '^.  +.*/digest-[^/]+' | " + "head -n-1"

    if cmd is not None:
        # Use Popen instead of getstatusoutput(), in order to avoid
        # unicode handling problems (see bug #310789).
        args = [BASH_BINARY, "-c", cmd]
        if sys.hexversion < 0x3000000 or sys.hexversion >= 0x3020000:
            # Python 3.1 does not support bytes in Popen args.
            args = [_unicode_encode(x) for x in args]
        proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        out = _unicode_decode(proc.communicate()[0])
        proc.wait()
        mylines = out.splitlines()
        myupdates = []
        for line in mylines:
            if not line:
                continue
            if (
                line[0] not in " UPMARD"
            ):  # unmodified(svn),Updates,Patches,Modified,Added,Removed/Replaced(svn),Deleted(svn)
                # Stray Manifest is fine, we will readd it anyway.
                if line[0] == "?" and line[1:].lstrip() == "Manifest":
                    continue
                logging.error(
                    red("!!! Please fix the following issues reported " + "from cvs: ") + green("(U,P,M,A,R,D are ok)")
                )
                logging.error(red("!!! Note: This is a pretend/no-modify pass..."))
                logging.error(out)
                sys.exit(1)
            elif vcs == "cvs" and line[0] in "UP":
                myupdates.append(line[2:])
            elif vcs == "svn" and line[8] == "*":
                myupdates.append(line[9:].lstrip(" 1234567890"))

        if myupdates:
            logging.info(green("Fetching trivial updates..."))
            if options.pretend:
                logging.info("(" + vcs + " update " + " ".join(myupdates) + ")")
                retval = os.EX_OK
            else:
                retval = os.system(vcs + " update " + " ".join(myupdates))
            if retval != os.EX_OK:
                logging.fatal("!!! " + vcs + " exited with an error. Terminating.")
                sys.exit(retval)