import pickle\r
import array\r
import shutil\r
+import filecmp\r
from random import sample\r
from struct import pack\r
import uuid\r
else:\r
Filename = BaseName + Path.BaseName\r
\r
- #\r
- # If -N is specified on command line, cache is disabled\r
- # The directory has to be created\r
- #\r
DbDir = os.path.split(GlobalData.gDatabasePath)[0]\r
- if not os.path.exists(DbDir):\r
- os.makedirs(DbDir)\r
+\r
#\r
# A temporary INF is copied to database path which must have write permission\r
# The temporary will be removed at the end of build\r
#\r
RtPath.Path = TempFullPath\r
RtPath.BaseName = BaseName\r
+ RtPath.OriginalPath = Path\r
#\r
# If file exists, compare contents\r
#\r
\r
return True\r
\r
+## Copy source file only if it is different from the destination file\r
+#\r
+# This method is used to copy file only if the source file and destination\r
+# file content are different. This is quite useful to avoid duplicated\r
+# file writing.\r
+#\r
+# @param SrcFile The path of source file\r
+# @param Dst The path of destination file or folder\r
+#\r
+# @retval True The two files content are different and the file is copied\r
+# @retval False No copy really happen\r
+#\r
+def CopyFileOnChange(SrcFile, Dst):\r
+ if not os.path.exists(SrcFile):\r
+ return False\r
+\r
+ if os.path.isdir(Dst):\r
+ DstFile = os.path.join(Dst, os.path.basename(SrcFile))\r
+ else:\r
+ DstFile = Dst\r
+\r
+ if os.path.exists(DstFile) and filecmp.cmp(SrcFile, DstFile, shallow=False):\r
+ return False\r
+\r
+ DirName = os.path.dirname(DstFile)\r
+ if not CreateDirectory(DirName):\r
+ EdkLogger.error(None, FILE_CREATE_FAILURE, "Could not create directory %s" % DirName)\r
+ else:\r
+ if DirName == '':\r
+ DirName = os.getcwd()\r
+ if not os.access(DirName, os.W_OK):\r
+ EdkLogger.error(None, PERMISSION_FAILURE, "Do not have write permission on directory %s" % DirName)\r
+\r
+ # os.replace and os.rename are the atomic operations in python 3 and 2.\r
+ # we use these two atomic operations to ensure the file copy is atomic:\r
+ # copy the src to a temp file in the dst same folder firstly, then\r
+ # replace or rename the temp file to the destination file.\r
+ with tempfile.NamedTemporaryFile(dir=DirName, delete=False) as tf:\r
+ shutil.copy(SrcFile, tf.name)\r
+ tempname = tf.name\r
+ try:\r
+ if hasattr(os, 'replace'):\r
+ os.replace(tempname, DstFile)\r
+ else:\r
+ # os.rename reqire to remove the dst on Windows, otherwise OSError will be raised.\r
+ if GlobalData.gIsWindows and os.path.exists(DstFile):\r
+ os.remove(DstFile)\r
+ os.rename(tempname, DstFile)\r
+\r
+ except IOError as X:\r
+ EdkLogger.error(None, FILE_COPY_FAILURE, ExtraData='IOError %s' % X)\r
+\r
+ return True\r
+\r
## Retrieve and cache the real path name in file system\r
#\r
# @param Root The root directory of path relative to\r
if CName in GuidKeys:\r
return P.Guids[CName]\r
return None\r
- return None\r
\r
## A string template class\r
#\r
p.stderr.close()\r
if err:\r
raise BadExpression("DevicePath: %s" % str(err))\r
- out = out.decode(encoding='utf-8', errors='ignore')\r
+ out = out.decode()\r
Size = len(out.split())\r
out = ','.join(out.split())\r
return '{' + out + '}', Size\r
self.TagName = TagName\r
self.ToolCode = ToolCode\r
self.ToolChainFamily = ToolChainFamily\r
+ self.OriginalPath = self\r
\r
## Convert the object of this class to a string\r
#\r