# ex:ts=4:sw=4:sts=4:et
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
#
# BitBake Build System Python Library
#
# Copyright (C) 2003 Holger Schurig
# Copyright (C) 2003, 2004 Chris Larson
#
# Based on Gentoo's portage.py.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
__version__ = "1.9.0"
__all__ = [
"debug",
"note",
"error",
"fatal",
"mkdirhier",
"movefile",
"tokenize",
"evaluate",
"flatten",
"relparse",
"ververify",
"isjustname",
"isspecific",
"pkgsplit",
"catpkgsplit",
"vercmp",
"pkgcmp",
"dep_parenreduce",
"dep_opconvert",
# fetch
"decodeurl",
"encodeurl",
# modules
"parse",
"data",
"command",
"event",
"build",
"fetch",
"manifest",
"methodpool",
"cache",
"runqueue",
"taskdata",
"providers",
]
whitespace = '\t\n\x0b\x0c\r '
lowercase = 'abcdefghijklmnopqrstuvwxyz'
import sys, os, types, re, string, bb
from bb import msg
#projectdir = os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))
projectdir = os.getcwd()
if "BBDEBUG" in os.environ:
level = int(os.environ["BBDEBUG"])
if level:
bb.msg.set_debug_level(level)
class VarExpandError(Exception):
pass
class MalformedUrl(Exception):
"""Exception raised when encountering an invalid url"""
#######################################################################
#######################################################################
#
# SECTION: Debug
#
# PURPOSE: little functions to make yourself known
#
#######################################################################
#######################################################################
def plain(*args):
bb.msg.warn(''.join(args))
def debug(lvl, *args):
bb.msg.debug(lvl, None, ''.join(args))
def note(*args):
bb.msg.note(1, None, ''.join(args))
def warn(*args):
bb.msg.warn(1, None, ''.join(args))
def error(*args):
bb.msg.error(None, ''.join(args))
def fatal(*args):
bb.msg.fatal(None, ''.join(args))
#######################################################################
#######################################################################
#
# SECTION: File
#
# PURPOSE: Basic file and directory tree related functions
#
#######################################################################
#######################################################################
def mkdirhier(dir):
"""Create a directory like 'mkdir -p', but does not complain if
directory already exists like os.makedirs
"""
debug(3, "mkdirhier(%s)" % dir)
try:
os.makedirs(dir)
debug(2, "created " + dir)
except OSError, e:
if e.errno != 17: raise e
#######################################################################
import stat
def movefile(src,dest,newmtime=None,sstat=None):
"""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("+src+","+dest+","+str(newmtime)+","+str(sstat)+")"
try:
if not sstat:
sstat=os.lstat(src)
except Exception, e:
print "movefile: Stating source file failed...", e
return None
destexists=1
try:
dstat=os.lstat(dest)
except:
dstat=os.lstat(os.path.dirname(dest))
destexists=0
if destexists:
if stat.S_ISLNK(dstat[stat.ST_MODE]):
try:
os.unlink(dest)
destexists=0
except Exception, e:
pass
if stat.S_ISLNK(sstat[stat.ST_MODE]):
try:
target=os.readlink(src)
if destexists and not stat.S_ISDIR(dstat[stat.ST_MODE]):
os.unlink(dest)
os.symlink(target,dest)
#os.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID])
os.unlink(src)
return os.lstat(dest)
except Exception, e:
print "movefile: failed to properly create symlink:", dest, "->", target, e
return None
renamefailed=1
if sstat[stat.ST_DEV]==dstat[stat.ST_DEV]:
try:
ret=os.rename(src,dest)
renamefailed=0
except Exception, e:
import errno
if e[0]!=errno.EXDEV:
# Some random error.
print "movefile: Failed to move", src, "to", dest, 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.
shutil.copyfile(src,dest+"#new")
os.rename(dest+"#new",dest)
didcopy=1
except Exception, e:
print 'movefile: copy', src, '->', dest, 'failed.', e
return None
else:
#we don't yet handle special, so we need to fall back to /bin/mv
a=getstatusoutput("/bin/mv -f "+"'"+src+"' '"+dest+"'")
if a[0]!=0:
print "movefile: Failed to move special file:" + src + "' to '" + dest + "'", a
return None # failure
try:
if didcopy:
missingos.lchown(dest,sstat[stat.ST_UID],sstat[stat.ST_GID
|