Merge "Revert "Use .KATI_RESTAT to reduce unnecessary rebuilds of .jar files""
diff --git a/core/Makefile b/core/Makefile
index 8922f06..c930708 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -1629,6 +1629,9 @@
$(hide) for part in $(AB_OTA_PARTITIONS); do \
echo "$${part}" >> $(zip_root)/META/ab_partitions.txt; \
done
+ $(hide) for conf in $(AB_OTA_POSTINSTALL_CONFIG); do \
+ echo "$${conf}" >> $(zip_root)/META/postinstall_config.txt; \
+ done
@# Include the build type in META/misc_info.txt so the server can easily differentiate production builds.
$(hide) echo "build_type=$(TARGET_BUILD_VARIANT)" >> $(zip_root)/META/misc_info.txt
ifdef OSRELEASED_DIRECTORY
diff --git a/core/binary.mk b/core/binary.mk
index d3b536d..028950a 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -730,8 +730,9 @@
$(transform-aidl-to-cpp)
-include $(addsuffix .P,$(basename $(aidl_gen_cpp)))
-# Add generated headers to include path.
+# Add generated headers to include paths.
my_c_includes += $(aidl_gen_include_root)
+my_export_c_include_dirs += $(aidl_gen_include_root)
# Pick up the generated C++ files later for transformation to .o files.
my_generated_sources += $(aidl_gen_cpp)
@@ -1301,7 +1302,10 @@
export_includes := $(intermediates)/export_includes
$(export_includes): PRIVATE_EXPORT_C_INCLUDE_DIRS := $(my_export_c_include_dirs)
# Make sure .pb.h are already generated before any dependent source files get compiled.
-$(export_includes) : $(LOCAL_MODULE_MAKEFILE_DEP) $(proto_generated_headers) $(dbus_generated_headers)
+# Similarly, the generated DBus headers need to exist before we export their location.
+# People are not going to consume the aidl generated cpp file, but the cpp file is
+# generated after the headers, so this is a convenient way to ensure the headers exist.
+$(export_includes) : $(LOCAL_MODULE_MAKEFILE_DEP) $(proto_generated_headers) $(dbus_generated_headers) $(aidl_gen_cpp)
@echo Export includes file: $< -- $@
$(hide) mkdir -p $(dir $@) && rm -f $@
ifdef my_export_c_include_dirs
diff --git a/core/clang/TARGET_arm64.mk b/core/clang/TARGET_arm64.mk
index 5120a6d..532ca77 100644
--- a/core/clang/TARGET_arm64.mk
+++ b/core/clang/TARGET_arm64.mk
@@ -66,6 +66,6 @@
TARGET_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-aarch64-android.a
# Address sanitizer clang config
-ADDRESS_SANITIZER_RUNTIME_LIBRARY := libclang_rt.asan-arm64-android
+ADDRESS_SANITIZER_RUNTIME_LIBRARY := libclang_rt.asan-aarch64-android
ADDRESS_SANITIZER_RPATH := /data/vendor/lib64:/$(TARGET_COPY_OUT_VENDOR)/lib64:/data/lib64
ADDRESS_SANITIZER_LINKER := /system/bin/linker_asan64
diff --git a/core/clang/config.mk b/core/clang/config.mk
index 03e8dd5..756bf49 100644
--- a/core/clang/config.mk
+++ b/core/clang/config.mk
@@ -1,7 +1,8 @@
## Clang configurations.
-LLVM_PREBUILTS_VERSION := 3.8
-LLVM_PREBUILTS_PATH := prebuilts/clang/host/$(BUILD_OS)-x86/$(LLVM_PREBUILTS_VERSION)/bin
+LLVM_PREBUILTS_VERSION ?= 3.8
+LLVM_PREBUILTS_BASE ?= prebuilts/clang/host
+LLVM_PREBUILTS_PATH := $(LLVM_PREBUILTS_BASE)/$(BUILD_OS)-x86/$(LLVM_PREBUILTS_VERSION)/bin
LLVM_RTLIB_PATH := $(LLVM_PREBUILTS_PATH)/../lib/clang/$(LLVM_PREBUILTS_VERSION)/lib/linux/
CLANG := $(LLVM_PREBUILTS_PATH)/clang$(BUILD_EXECUTABLE_SUFFIX)
diff --git a/core/definitions.mk b/core/definitions.mk
index 0089865..e6f4a04 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -530,7 +530,7 @@
$(error $(LOCAL_PATH): Name not defined in call to generated-sources-dir-for)) \
$(eval _idfPrefix := $(if $(strip $(3)),HOST,TARGET)) \
$(if $(filter $(_idfPrefix)-$(_idfClass),$(COMMON_MODULE_CLASSES))$(4), \
- $(eval _idfIntBase := $($(_idfPrefix)_OUT_GEN_COMMON)) \
+ $(eval _idfIntBase := $($(_idfPrefix)_OUT_COMMON_GEN)) \
, \
$(eval _idfIntBase := $($(_idfPrefix)_OUT_GEN)) \
) \
@@ -1760,7 +1760,8 @@
endef
# For a list of jar files, unzip them to a specified directory,
-# but make sure that no META-INF files come along for the ride.
+# but make sure that no META-INF files come along for the ride,
+# unless PRIVATE_DONT_DELETE_JAR_META_INF is set.
#
# $(1): files to unzip
# $(2): destination directory
@@ -1772,8 +1773,8 @@
exit 1; \
fi; \
unzip -qo $$f -d $(2); \
- done \
- $(if $(PRIVATE_DONT_DELETE_JAR_META_INF),,;rm -rf $(2)/META-INF)
+ done
+ $(if $(PRIVATE_DONT_DELETE_JAR_META_INF),,$(hide) rm -rf $(2)/META-INF)
endef
# Call jack
@@ -1875,7 +1876,7 @@
$(hide) mkdir -p $@.res.tmp
$(hide) $(call create-empty-package-at,$@.res.tmp.zip)
$(hide) $(call add-java-resources-to,$@.res.tmp.zip)
- $(hide) $(call unzip-jar-files,$@.res.tmp.zip,$@.res.tmp)
+ $(hide) unzip -qo $@.res.tmp.zip -d $@.res.tmp
$(hide) rm $@.res.tmp.zip)
$(hide) if [ -s $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq ] ; then \
export tmpEcjArg="@$(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq"; \
@@ -1915,7 +1916,7 @@
$(hide) mkdir -p $(dir $@)
$(JILL) $(PRIVATE_JILL_FLAGS) --output $@.tmpjill.jack $<
$(hide) mkdir -p $@.tmpjill.res
- $(hide) $(call unzip-jar-files,$<,$@.tmpjill.res)
+ $(hide) unzip -qo $< -d $@.tmpjill.res
$(hide) find $@.tmpjill.res -iname "*.class" -delete
$(hide) $(call call-jack) \
-D jack.import.resource.policy=keep-first \
diff --git a/core/droiddoc.mk b/core/droiddoc.mk
index 74f7d8b..1e9de1c 100644
--- a/core/droiddoc.mk
+++ b/core/droiddoc.mk
@@ -171,7 +171,7 @@
javadoc \
-encoding UTF-8 \
\@$(PRIVATE_SRC_LIST_FILE) \
- -J-Xmx1280m \
+ -J-Xmx1600m \
-XDignore.symbol.file \
$(PRIVATE_PROFILING_OPTIONS) \
-quiet \
diff --git a/core/goma.mk b/core/goma.mk
index ddd7d80..01a1d81 100644
--- a/core/goma.mk
+++ b/core/goma.mk
@@ -56,7 +56,11 @@
# gomacc can start goma client's daemon process automatically, but
# it is safer and faster to start up it beforehand. We run this as a
# background process so this won't slow down the build.
- $(shell $(goma_ctl) ensure_start &> /dev/null &)
+ # We use "ensure_start" command when the compiler_proxy is already
+ # running and uses GOMA_HERMETIC=error flag. The compiler_proxy will
+ # restart otherwise.
+ # TODO(hamaji): Remove this condition after http://b/25676777 is fixed.
+ $(shell ( if ( curl http://localhost:$$($(GOMA_CC) port)/flagz | grep GOMA_HERMETIC=error ); then cmd=ensure_start; else cmd=restart; fi; GOMA_HERMETIC=error $(goma_ctl) $${cmd} ) &> /dev/null &)
goma_ctl :=
goma_dir :=
diff --git a/core/main.mk b/core/main.mk
index 2bd3163..d9ff68e 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -113,6 +113,11 @@
$(shell rm -f $(OUT_DIR)/ninja_build)
endif
+# With these files findleaves.py won't be unnecessarily slower even if
+# there is a user creates a copy of $(OUT_DIR).
+$(shell echo '# This file prevents findleaves.py from traversing this directory further' > $(OUT_DIR)/Android.mk)
+$(shell echo '# This file prevents findleaves.py from traversing this directory further' > $(OUT_DIR)/CleanSpec.mk)
+
# Write the build number to a file so it can be read back in
# without changing the command line every time. Avoids rebuilds
# when using ninja.
diff --git a/core/ninja.mk b/core/ninja.mk
index 2e8f3c8..862ed80 100644
--- a/core/ninja.mk
+++ b/core/ninja.mk
@@ -1,5 +1,6 @@
KATI ?= $(HOST_OUT_EXECUTABLES)/ckati
MAKEPARALLEL ?= $(HOST_OUT_EXECUTABLES)/makeparallel
+NINJA ?= prebuilts/ninja/$(HOST_PREBUILT_TAG)/ninja
KATI_OUTPUT_PATTERNS := $(OUT_DIR)/build%.ninja $(OUT_DIR)/ninja%.sh
@@ -89,7 +90,7 @@
endif
KATI_BUILD_NINJA := $(OUT_DIR)/build$(KATI_NINJA_SUFFIX).ninja
-KATI_NINJA_SH := $(OUT_DIR)/ninja$(KATI_NINJA_SUFFIX).sh
+KATI_ENV_SH := $(OUT_DIR)/env$(KATI_NINJA_SUFFIX).sh
# Write out a file mapping checksum to the real suffix.
ifneq ($(my_checksum_suffix),)
@@ -123,7 +124,7 @@
.PHONY: ninja_wrapper
ninja_wrapper: $(KATI_BUILD_NINJA) $(MAKEPARALLEL)
@echo Starting build with ninja
- +$(hide) PATH=prebuilts/ninja/$(HOST_PREBUILT_TAG)/:$$PATH NINJA_STATUS="$(NINJA_STATUS)" $(NINJA_MAKEPARALLEL) $(KATI_NINJA_SH) $(NINJA_GOALS) -C $(TOP) $(NINJA_ARGS)
+ +$(hide) export NINJA_STATUS="$(NINJA_STATUS)" && source $(KATI_ENV_SH) && $(NINJA_MAKEPARALLEL) $(NINJA) $(NINJA_GOALS) -C $(TOP) -f $(KATI_BUILD_NINJA) $(NINJA_ARGS)
KATI_FIND_EMULATOR := --use_find_emulator
ifeq ($(KATI_EMULATE_FIND),false)
diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk
index 3af7101..da76eb9 100644
--- a/core/prebuilt_internal.mk
+++ b/core/prebuilt_internal.mk
@@ -275,8 +275,13 @@
$(built_module) : $(my_prebuilt_src_file)
$(transform-prebuilt-to-target-strip-comments)
else
+ifneq ($(LOCAL_ACP_UNAVAILABLE),true)
$(built_module) : $(my_prebuilt_src_file) | $(ACP)
$(transform-prebuilt-to-target)
+else
+$(built_module) : $(my_prebuilt_src_file)
+ $(copy-file-to-target-with-cp)
+endif
endif
endif # LOCAL_MODULE_CLASS != APPS
diff --git a/envsetup.sh b/envsetup.sh
index 45f70b3..f266f1a 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -1413,11 +1413,7 @@
\cd $T/$pathname
}
-# Force JAVA_HOME to point to java 1.7 if it isn't already set.
-#
-# Note that the MacOS path for java 1.7 includes a minor revision number (sigh).
-# For some reason, installing the JDK doesn't make it show up in the
-# JavaVM.framework/Versions/1.7/ folder.
+# Force JAVA_HOME to point to java 1.7/1.8 if it isn't already set.
function set_java_home() {
# Clear the existing JAVA_HOME value if we set it ourselves, so that
# we can reset it later, depending on the version of java the build
@@ -1430,14 +1426,25 @@
fi
if [ ! "$JAVA_HOME" ]; then
- case `uname -s` in
- Darwin)
- export JAVA_HOME=$(/usr/libexec/java_home -v 1.7)
- ;;
- *)
- export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
- ;;
- esac
+ if [ ! "$EXPERIMENTAL_USE_JAVA8" ]; then
+ case `uname -s` in
+ Darwin)
+ export JAVA_HOME=$(/usr/libexec/java_home -v 1.7)
+ ;;
+ *)
+ export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
+ ;;
+ esac
+ else
+ case `uname -s` in
+ Darwin)
+ export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
+ ;;
+ *)
+ export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
+ ;;
+ esac
+ fi
# Keep track of the fact that we set JAVA_HOME ourselves, so that
# we can change it on the next envsetup.sh, if required.
diff --git a/target/board/generic_mips/BoardConfig.mk b/target/board/generic_mips/BoardConfig.mk
index 76a2ef4..50924f8 100644
--- a/target/board/generic_mips/BoardConfig.mk
+++ b/target/board/generic_mips/BoardConfig.mk
@@ -61,3 +61,5 @@
TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
BOARD_SEPOLICY_DIRS += build/target/board/generic/sepolicy
+
+USE_CLANG_PLATFORM_BUILD := true
diff --git a/target/board/generic_mips64/BoardConfig.mk b/target/board/generic_mips64/BoardConfig.mk
index 8e8a68b..d5430cd 100644
--- a/target/board/generic_mips64/BoardConfig.mk
+++ b/target/board/generic_mips64/BoardConfig.mk
@@ -75,3 +75,5 @@
BOARD_SEPOLICY_DIRS += build/target/board/generic/sepolicy
DEX_PREOPT_DEFAULT := nostripping
+
+USE_CLANG_PLATFORM_BUILD := true
diff --git a/target/product/aosp_arm.mk b/target/product/aosp_arm.mk
index 86b715c..781cae6 100644
--- a/target/product/aosp_arm.mk
+++ b/target/product/aosp_arm.mk
@@ -13,6 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/full.mk)
+include $(SRC_TARGET_DIR)/product/full.mk
PRODUCT_NAME := aosp_arm
diff --git a/target/product/aosp_mips.mk b/target/product/aosp_mips.mk
index ceeb433..a76b93a 100644
--- a/target/product/aosp_mips.mk
+++ b/target/product/aosp_mips.mk
@@ -13,6 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/full_mips.mk)
+include $(SRC_TARGET_DIR)/product/full_mips.mk
PRODUCT_NAME := aosp_mips
diff --git a/target/product/aosp_x86.mk b/target/product/aosp_x86.mk
index 3e9b018..cba43c4 100644
--- a/target/product/aosp_x86.mk
+++ b/target/product/aosp_x86.mk
@@ -13,6 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-$(call inherit-product, $(SRC_TARGET_DIR)/product/full_x86.mk)
+include $(SRC_TARGET_DIR)/product/full_x86.mk
PRODUCT_NAME := aosp_x86
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index b6cee63..7cb9072 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -319,6 +319,23 @@
banner("cache")
AddCache(output_zip)
+ # For devices using A/B update, copy over images from RADIO/ to IMAGES/ and
+ # make sure we have all the needed images ready under IMAGES/.
+ ab_partitions = os.path.join(OPTIONS.input_tmp, "META", "ab_partitions.txt")
+ if os.path.exists(ab_partitions):
+ with open(ab_partitions, 'r') as f:
+ lines = f.readlines()
+ for line in lines:
+ img_name = line.strip() + ".img"
+ img_radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
+ if os.path.exists(img_radio_path):
+ common.ZipWrite(output_zip, img_radio_path,
+ os.path.join("IMAGES", img_name))
+
+ # Zip spec says: All slashes MUST be forward slashes.
+ img_path = 'IMAGES/' + img_name
+ assert img_path in output_zip.namelist(), "cannot find " + img_name
+
common.ZipClose(output_zip)
def main(argv):
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 872dd4c..2c8bbc6 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -211,8 +211,11 @@
makeint("boot_size")
makeint("fstab_version")
- d["fstab"] = LoadRecoveryFSTab(read_helper, d["fstab_version"],
- d.get("system_root_image", False))
+ if d.get("no_recovery", False) == "true":
+ d["fstab"] = None
+ else:
+ d["fstab"] = LoadRecoveryFSTab(read_helper, d["fstab_version"],
+ d.get("system_root_image", False))
d["build.prop"] = LoadBuildProp(read_helper)
return d
diff --git a/tools/signapk/SignApk.java b/tools/signapk/SignApk.java
index 3ddab11..740a343 100644
--- a/tools/signapk/SignApk.java
+++ b/tools/signapk/SignApk.java
@@ -135,7 +135,6 @@
/** Returns the expected signature algorithm for this key type. */
private static String getSignatureAlgorithm(X509Certificate cert) {
- String sigAlg = cert.getSigAlgName().toUpperCase(Locale.US);
String keyType = cert.getPublicKey().getAlgorithm().toUpperCase(Locale.US);
if ("RSA".equalsIgnoreCase(keyType)) {
if (getDigestAlgorithm(cert) == USE_SHA256) {
@@ -246,8 +245,11 @@
* Now it's in a PKCS#8 PrivateKeyInfo structure. Read its Algorithm
* OID and use that to construct a KeyFactory.
*/
- ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(spec.getEncoded()));
- PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject());
+ PrivateKeyInfo pki;
+ try (ASN1InputStream bIn =
+ new ASN1InputStream(new ByteArrayInputStream(spec.getEncoded()))) {
+ pki = PrivateKeyInfo.getInstance(bIn.readObject());
+ }
String algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId();
return KeyFactory.getInstance(algOid).generatePrivate(spec);
@@ -461,9 +463,10 @@
gen.addCertificates(certs);
CMSSignedData sigData = gen.generate(data, false);
- ASN1InputStream asn1 = new ASN1InputStream(sigData.getEncoded());
- DEROutputStream dos = new DEROutputStream(out);
- dos.writeObject(asn1.readObject());
+ try (ASN1InputStream asn1 = new ASN1InputStream(sigData.getEncoded())) {
+ DEROutputStream dos = new DEROutputStream(out);
+ dos.writeObject(asn1.readObject());
+ }
}
/**
@@ -616,7 +619,6 @@
private File publicKeyFile;
private X509Certificate publicKey;
private PrivateKey privateKey;
- private String outputFile;
private OutputStream outputStream;
private final ASN1ObjectIdentifier type;
private WholeFileSignerOutputStream signer;
@@ -636,14 +638,17 @@
* This should actually return byte[] or something similar, but nothing
* actually checks it currently.
*/
+ @Override
public Object getContent() {
return this;
}
+ @Override
public ASN1ObjectIdentifier getContentType() {
return type;
}
+ @Override
public void write(OutputStream out) throws IOException {
try {
signer = new WholeFileSignerOutputStream(out, outputStream);
@@ -658,7 +663,7 @@
copyFiles(manifest, inputJar, outputJar, timestamp, 0);
addOtacert(outputJar, publicKeyFile, timestamp, manifest, hash);
- signFile(manifest, inputJar,
+ signFile(manifest,
new X509Certificate[]{ publicKey },
new PrivateKey[]{ privateKey },
outputJar);
@@ -753,7 +758,7 @@
temp.writeTo(outputStream);
}
- private static void signFile(Manifest manifest, JarFile inputJar,
+ private static void signFile(Manifest manifest,
X509Certificate[] publicKey, PrivateKey[] privateKey,
JarOutputStream outputJar)
throws Exception {
@@ -860,7 +865,6 @@
boolean signWholeFile = false;
String providerClass = null;
- String providerArg = null;
int alignment = 4;
int argstart = 0;
@@ -944,7 +948,7 @@
Manifest manifest = addDigestsToManifest(inputJar, hashes);
copyFiles(manifest, inputJar, outputJar, timestamp, alignment);
- signFile(manifest, inputJar, publicKey, privateKey, outputJar);
+ signFile(manifest, publicKey, privateKey, outputJar);
outputJar.close();
}
} catch (Exception e) {
diff --git a/tools/target_files_diff.py b/tools/target_files_diff.py
index 010ea84..405c42b 100755
--- a/tools/target_files_diff.py
+++ b/tools/target_files_diff.py
@@ -26,6 +26,7 @@
import os
import re
import subprocess
+import sys
import tempfile
def ignore(name):
@@ -94,14 +95,16 @@
def trim_install_recovery(original, new):
"""
- Rewrite the install-recovery script to remove the hash of the recovery partition.
+ Rewrite the install-recovery script to remove the hash of the recovery
+ partition.
"""
for line in original:
new.write(re.sub(r'[0-9a-f]{40}', '0'*40, line))
def sort_file(original, new):
"""
- Sort the file. Some OTA metadata files are not in a deterministic order currently.
+ Sort the file. Some OTA metadata files are not in a deterministic order
+ currently.
"""
lines = original.readlines()
lines.sort()
@@ -126,7 +129,8 @@
@contextlib.contextmanager
def preprocess(name, filename):
"""
- Optionally rewrite files before diffing them, to remove known-variable information.
+ Optionally rewrite files before diffing them, to remove known-variable
+ information.
"""
if name in REWRITE_RULES:
with tempfile.NamedTemporaryFile() as newfp:
@@ -137,24 +141,25 @@
else:
yield filename
-def diff(name, file1, file2):
+def diff(name, file1, file2, out_file):
"""
Diff a file pair with diff, running preprocess() on the arguments first.
"""
with preprocess(name, file1) as f1:
with preprocess(name, file2) as f2:
- proc = subprocess.Popen(['diff', f1, f2], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- (stdout, ignore) = proc.communicate()
+ proc = subprocess.Popen(['diff', f1, f2], stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ (stdout, _) = proc.communicate()
if proc.returncode == 0:
return
stdout = stdout.strip()
if stdout == 'Binary files %s and %s differ' % (f1, f2):
- print("%s: Binary files differ" % name)
+ print("%s: Binary files differ" % name, file=out_file)
else:
for line in stdout.strip().split('\n'):
- print("%s: %s" % (name, line))
+ print("%s: %s" % (name, line), file=out_file)
-def recursiveDiff(prefix, dir1, dir2):
+def recursiveDiff(prefix, dir1, dir2, out_file):
"""
Recursively diff two directories, checking metadata then calling diff()
"""
@@ -175,31 +180,34 @@
link1 = os.readlink(name1)
link2 = os.readlink(name2)
if link1 != link2:
- print("%s: Symlinks differ: %s vs %s" % (name, link1, link2))
+ print("%s: Symlinks differ: %s vs %s" % (name, link1, link2),
+ file=out_file)
else:
- print("%s: File types differ, skipping compare" % name)
+ print("%s: File types differ, skipping compare" % name,
+ file=out_file)
continue
stat1 = os.stat(name1)
stat2 = os.stat(name2)
- type1 = stat1.st_mode & ~0777
- type2 = stat2.st_mode & ~0777
+ type1 = stat1.st_mode & ~0o777
+ type2 = stat2.st_mode & ~0o777
if type1 != type2:
- print("%s: File types differ, skipping compare" % name)
+ print("%s: File types differ, skipping compare" % name, file=out_file)
continue
if stat1.st_mode != stat2.st_mode:
- print("%s: Modes differ: %o vs %o" % (name, stat1.st_mode, stat2.st_mode))
+ print("%s: Modes differ: %o vs %o" %
+ (name, stat1.st_mode, stat2.st_mode), file=out_file)
if os.path.isdir(name1):
- recursiveDiff(name, name1, name2)
+ recursiveDiff(name, name1, name2, out_file)
elif os.path.isfile(name1):
- diff(name, name1, name2)
+ diff(name, name1, name2, out_file)
else:
- print("%s: Unknown file type, skipping compare" % name)
+ print("%s: Unknown file type, skipping compare" % name, file=out_file)
else:
- print("%s: Only in base package" % name)
+ print("%s: Only in base package" % name, file=out_file)
for entry in list2:
name = os.path.join(prefix, entry)
@@ -210,15 +218,25 @@
continue
if entry not in list1:
- print("%s: Only in new package" % name)
+ print("%s: Only in new package" % name, file=out_file)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('dir1', help='The base target files package (extracted)')
parser.add_argument('dir2', help='The new target files package (extracted)')
+ parser.add_argument('--output',
+ help='The output file, otherwise it prints to stdout')
args = parser.parse_args()
- recursiveDiff('', args.dir1, args.dir2)
+ if args.output:
+ out_file = open(args.output, 'w')
+ else:
+ out_file = sys.stdout
+
+ recursiveDiff('', args.dir1, args.dir2, out_file)
+
+ if args.output:
+ out_file.close()
if __name__ == '__main__':
main()