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)
def testBashSyntax(self): for parent, dirs, files in os.walk(PORTAGE_BIN_PATH): parent = _unicode_decode(parent, encoding=_encodings['fs'], errors='strict') for x in files: x = _unicode_decode(x, encoding=_encodings['fs'], errors='strict') ext = x.split('.')[-1] if ext in ('.py', '.pyc', '.pyo'): continue x = os.path.join(parent, x) st = os.lstat(x) if not stat.S_ISREG(st.st_mode): continue # Check for bash shebang f = open( _unicode_encode(x, encoding=_encodings['fs'], errors='strict'), 'rb') line = _unicode_decode(f.readline(), encoding=_encodings['content'], errors='replace') f.close() if line[:2] == '#!' and \ 'bash' in line: cmd = "%s -n %s" % (_shell_quote(BASH_BINARY), _shell_quote(x)) status, output = subprocess_getstatusoutput(cmd) self.assertEqual(os.WIFEXITED(status) and \ os.WEXITSTATUS(status) == os.EX_OK, True, msg=output)
def get_term_size(): """ Get the number of lines and columns of the tty that is connected to stdout. Returns a tuple of (lines, columns) or (-1, -1) if an error occurs. The curses module is used if available, otherwise the output of `stty size` is parsed. """ if not sys.stdout.isatty(): return -1, -1 try: import curses try: curses.setupterm() return curses.tigetnum('lines'), curses.tigetnum('cols') except curses.error: pass except ImportError: pass st, out = portage.subprocess_getstatusoutput('stty size') if st == os.EX_OK: out = out.split() if len(out) == 2: try: return int(out[0]), int(out[1]) except ValueError: pass return -1, -1
def testBashSyntax(self): for parent, dirs, files in os.walk(PORTAGE_BIN_PATH): parent = _unicode_decode(parent, encoding=_encodings['fs'], errors='strict') for x in files: x = _unicode_decode(x, encoding=_encodings['fs'], errors='strict') ext = x.split('.')[-1] if ext in ('.py', '.pyc', '.pyo'): continue x = os.path.join(parent, x) st = os.lstat(x) if not stat.S_ISREG(st.st_mode): continue # Check for bash shebang f = open(_unicode_encode(x, encoding=_encodings['fs'], errors='strict'), 'rb') line = _unicode_decode(f.readline(), encoding=_encodings['content'], errors='replace') f.close() if line[:2] == '#!' and \ 'bash' in line: cmd = "%s -n %s" % (_shell_quote(BASH_BINARY), _shell_quote(x)) status, output = subprocess_getstatusoutput(cmd) self.assertEqual(os.WIFEXITED(status) and \ os.WEXITSTATUS(status) == os.EX_OK, True, msg=output)
def get_term_size(): """ Get the number of lines and columns of the tty that is connected to stdout. Returns a tuple of (lines, columns) or (0, 0) if an error occurs. The curses module is used if available, otherwise the output of `stty size` is parsed. The lines and columns values are guaranteed to be greater than or equal to zero, since a negative COLUMNS variable is known to prevent some commands from working (see bug #394091). """ if not sys.stdout.isatty(): return (0, 0) try: import curses try: curses.setupterm() return curses.tigetnum('lines'), curses.tigetnum('cols') except curses.error: pass except ImportError: pass st, out = portage.subprocess_getstatusoutput('stty size') if st == os.EX_OK: out = out.split() if len(out) == 2: try: val = (int(out[0]), int(out[1])) except ValueError: pass else: if val[0] >= 0 and val[1] >= 0: return val return (0, 0)
def find_updated_config_files(target_root, config_protect): """ Return a tuple of configuration files that needs to be updated. The tuple contains lists organized like this: [ protected_dir, file_list ] If the protected config isn't a protected_dir but a procted_file, list is: [ protected_file, None ] If no configuration files needs to be updated, None is returned """ os = _os_merge if config_protect: # directories with some protect files in them for x in config_protect: files = [] x = os.path.join(target_root, x.lstrip(os.path.sep)) if not os.access(x, os.W_OK): continue try: mymode = os.lstat(x).st_mode except OSError: continue if stat.S_ISLNK(mymode): # We want to treat it like a directory if it # is a symlink to an existing directory. try: real_mode = os.stat(x).st_mode if stat.S_ISDIR(real_mode): mymode = real_mode except OSError: pass if stat.S_ISDIR(mymode): mycommand = \ "find '%s' -name '.*' -type d -prune -o -name '._cfg????_*'" % x else: mycommand = "find '%s' -maxdepth 1 -name '._cfg????_%s'" % \ os.path.split(x.rstrip(os.path.sep)) mycommand += " ! -name '.*~' ! -iname '.*.bak' -print0" a = subprocess_getstatusoutput(mycommand) if a[0] == 0: files = a[1].split('\0') # split always produces an empty string as the last element if files and not files[-1]: del files[-1] if files: if stat.S_ISDIR(mymode): yield (x, files) else: yield (x, None)
def diffstatusoutput_len(cmd): """ Execute the string cmd in a shell with getstatusoutput() and return a 2-tuple (status, output_length). If getstatusoutput() raises UnicodeDecodeError (known to happen with python3.1), return a 2-tuple (1, 1). This provides a simple way to check for non-zero output length of diff commands, while providing simple handling of UnicodeDecodeError when necessary. """ try: status, output = portage.subprocess_getstatusoutput(cmd) return (status, len(output)) except UnicodeDecodeError: return (1, 1)
def _get_target(self): global userpriv_groups if userpriv_groups is not self: return userpriv_groups userpriv_groups = _userpriv_groups # Get a list of group IDs for the portage user. Do not use # grp.getgrall() since it is known to trigger spurious # SIGPIPE problems with nss_ldap. mystatus, myoutput = \ portage.subprocess_getstatusoutput("id -G %s" % _portage_uname) if mystatus == os.EX_OK: for x in myoutput.split(): try: userpriv_groups.append(int(x)) except ValueError: pass userpriv_groups[:] = sorted(set(userpriv_groups)) return userpriv_groups
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)
def _get_global(k): if k in _initialized_globals: return globals()[k] if k in ('portage_gid', 'portage_uid', 'secpass'): global portage_gid, portage_uid, secpass secpass = 0 if uid == 0: secpass = 2 elif portage.const.EPREFIX: secpass = 2 #Discover the uid and gid of the portage user/group try: portage_uid = pwd.getpwnam(_get_global('_portage_username')).pw_uid _portage_grpname = _get_global('_portage_grpname') if platform.python_implementation() == 'PyPy': # Somehow this prevents "TypeError: expected string" errors # from grp.getgrnam() with PyPy 1.7 _portage_grpname = str(_portage_grpname) portage_gid = grp.getgrnam(_portage_grpname).gr_gid if secpass < 1 and portage_gid in os.getgroups(): secpass = 1 except KeyError: portage_uid = 0 portage_gid = 0 writemsg(colorize("BAD", _("portage: 'portage' user or group missing.")) + "\n", noiselevel=-1) writemsg(_( " For the defaults, line 1 goes into passwd, " "and 2 into group.\n"), noiselevel=-1) writemsg(colorize("GOOD", " portage:x:250:250:portage:/var/tmp/portage:/bin/false") \ + "\n", noiselevel=-1) writemsg(colorize("GOOD", " portage::250:portage") + "\n", noiselevel=-1) portage_group_warning() _initialized_globals.add('portage_gid') _initialized_globals.add('portage_uid') _initialized_globals.add('secpass') if k == 'portage_gid': return portage_gid elif k == 'portage_uid': return portage_uid elif k == 'secpass': return secpass else: raise AssertionError('unknown name: %s' % k) elif k == 'userpriv_groups': v = [portage_gid] if secpass >= 2: # Get a list of group IDs for the portage user. Do not use # grp.getgrall() since it is known to trigger spurious # SIGPIPE problems with nss_ldap. mystatus, myoutput = \ portage.subprocess_getstatusoutput("id -G %s" % _portage_username) if mystatus == os.EX_OK: for x in myoutput.split(): try: v.append(int(x)) except ValueError: pass v = sorted(set(v)) # Avoid instantiating portage.settings when the desired # variable is set in os.environ. elif k in ('_portage_grpname', '_portage_username'): v = None if k == '_portage_grpname': env_key = 'PORTAGE_GRPNAME' else: env_key = 'PORTAGE_USERNAME' if env_key in os.environ: v = os.environ[env_key] elif hasattr(portage, 'settings'): v = portage.settings.get(env_key) elif portage.const.EPREFIX: # For prefix environments, default to the UID and GID of # the top-level EROOT directory. The config class has # equivalent code, but we also need to do it here if # _disable_legacy_globals() has been called. eroot = os.path.join(os.environ.get('ROOT', os.sep), portage.const.EPREFIX.lstrip(os.sep)) try: eroot_st = os.stat(eroot) except OSError: pass else: if k == '_portage_grpname': try: grp_struct = grp.getgrgid(eroot_st.st_gid) except KeyError: pass else: v = grp_struct.gr_name else: try: pwd_struct = pwd.getpwuid(eroot_st.st_uid) except KeyError: pass else: v = pwd_struct.pw_name if v is None: v = 'portage' else: raise AssertionError('unknown name: %s' % k) globals()[k] = v _initialized_globals.add(k) return v
pass # There is only one implementation for size def getsize(filename): size = os.stat(filename).st_size return (size, size) hashfunc_map["size"] = getsize # end actual hash functions prelink_capable = False if os.path.exists(PRELINK_BINARY): results = portage.subprocess_getstatusoutput( "%s --version > /dev/null 2>&1" % (PRELINK_BINARY, )) if (results[0] >> 8) == 0: prelink_capable = 1 del results def is_prelinkable_elf(filename): f = _open_file(filename) try: magic = f.read(17) finally: f.close() return (len(magic) == 17 and magic.startswith(b'\x7fELF') and magic[16] in (b'\x02', b'\x03')) # 2=ET_EXEC, 3=ET_DYN
def _get_global(k): if k in _initialized_globals: return globals()[k] if k in ('portage_gid', 'portage_uid', 'secpass'): global portage_gid, portage_uid, secpass secpass = 0 if uid == 0: secpass = 2 elif portage.const.EPREFIX: secpass = 2 #Discover the uid and gid of the portage user/group try: portage_uid = pwd.getpwnam(_get_global('_portage_username')).pw_uid _portage_grpname = _get_global('_portage_grpname') if platform.python_implementation() == 'PyPy': # Somehow this prevents "TypeError: expected string" errors # from grp.getgrnam() with PyPy 1.7 _portage_grpname = str(_portage_grpname) portage_gid = grp.getgrnam(_portage_grpname).gr_gid if secpass < 1 and portage_gid in os.getgroups(): secpass = 1 except KeyError: portage_uid = 0 portage_gid = 0 writemsg(colorize( "BAD", _("portage: 'portage' user or group missing.")) + "\n", noiselevel=-1) writemsg(_(" For the defaults, line 1 goes into passwd, " "and 2 into group.\n"), noiselevel=-1) writemsg(colorize("GOOD", " portage:x:250:250:portage:/var/tmp/portage:/bin/false") \ + "\n", noiselevel=-1) writemsg(colorize("GOOD", " portage::250:portage") + "\n", noiselevel=-1) portage_group_warning() _initialized_globals.add('portage_gid') _initialized_globals.add('portage_uid') _initialized_globals.add('secpass') if k == 'portage_gid': return portage_gid elif k == 'portage_uid': return portage_uid elif k == 'secpass': return secpass else: raise AssertionError('unknown name: %s' % k) elif k == 'userpriv_groups': v = [portage_gid] if secpass >= 2: # Get a list of group IDs for the portage user. Do not use # grp.getgrall() since it is known to trigger spurious # SIGPIPE problems with nss_ldap. mystatus, myoutput = \ portage.subprocess_getstatusoutput("id -G %s" % _portage_username) if mystatus == os.EX_OK: for x in myoutput.split(): try: v.append(int(x)) except ValueError: pass v = sorted(set(v)) # Avoid instantiating portage.settings when the desired # variable is set in os.environ. elif k in ('_portage_grpname', '_portage_username'): v = None if k == '_portage_grpname': env_key = 'PORTAGE_GRPNAME' else: env_key = 'PORTAGE_USERNAME' if env_key in os.environ: v = os.environ[env_key] elif hasattr(portage, 'settings'): v = portage.settings.get(env_key) elif portage.const.EPREFIX: # For prefix environments, default to the UID and GID of # the top-level EROOT directory. The config class has # equivalent code, but we also need to do it here if # _disable_legacy_globals() has been called. eroot = os.path.join(os.environ.get('ROOT', os.sep), portage.const.EPREFIX.lstrip(os.sep)) try: eroot_st = os.stat(eroot) except OSError: pass else: if k == '_portage_grpname': try: grp_struct = grp.getgrgid(eroot_st.st_gid) except KeyError: pass else: v = grp_struct.gr_name else: try: pwd_struct = pwd.getpwuid(eroot_st.st_uid) except KeyError: pass else: v = pwd_struct.pw_name if v is None: v = 'portage' else: raise AssertionError('unknown name: %s' % k) globals()[k] = v _initialized_globals.add(k) return v
hashorigin_map["MD5"] = "python-fchksum" except ImportError: pass # There is only one implementation for size def getsize(filename): size = os.stat(filename).st_size return (size, size) hashfunc_map["size"] = getsize # end actual hash functions prelink_capable = False if os.path.exists(PRELINK_BINARY): results = portage.subprocess_getstatusoutput( "%s --version > /dev/null 2>&1" % (PRELINK_BINARY,)) if (results[0] >> 8) == 0: prelink_capable=1 del results def is_prelinkable_elf(filename): f = _open_file(filename) try: magic = f.read(17) finally: f.close() return (len(magic) == 17 and magic.startswith(b'\x7fELF') and magic[16] in (b'\x02', b'\x03')) # 2=ET_EXEC, 3=ET_DYN def perform_md5(x, calc_prelink=0): return perform_checksum(x, "MD5", calc_prelink)[0]