ninja/mac: Let mac_bundle_resources keep file permissions.

Also add a test that this is true for 'copies' too.

BUG=chromium:315383
R=mark@chromium.org

Review URL: https://codereview.chromium.org/61293004

git-svn-id: http://gyp.googlecode.com/svn/trunk@1779 78cadc50-ecff-11dd-a971-7dbc132099af
diff --git a/pylib/gyp/mac_tool.py b/pylib/gyp/mac_tool.py
index 03a7ebb..20b3a48 100755
--- a/pylib/gyp/mac_tool.py
+++ b/pylib/gyp/mac_tool.py
@@ -48,6 +48,9 @@
     extension = os.path.splitext(source)[1].lower()
     if os.path.isdir(source):
       # Copy tree.
+      # TODO(thakis): This copies file attributes like mtime, while the
+      # single-file branch below doesn't. This should probably be changed to
+      # be consistent with the single-file branch.
       if os.path.exists(dest):
         shutil.rmtree(dest)
       shutil.copytree(source, dest)
@@ -58,7 +61,7 @@
     elif extension == '.strings':
       self._CopyStringsFile(source, dest)
     else:
-      shutil.copyfile(source, dest)
+      shutil.copy(source, dest)
 
   def _CopyXIBFile(self, source, dest):
     """Compiles a XIB file with ibtool into a binary plist in the bundle."""
diff --git a/test/copies/gyptest-attribs.py b/test/copies/gyptest-attribs.py
new file mode 100644
index 0000000..70d717a
--- /dev/null
+++ b/test/copies/gyptest-attribs.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Verifies that copying files preserves file attributes.
+"""
+
+import TestGyp
+
+import os
+import stat
+import sys
+
+
+def check_attribs(path, expected_exec_bit):
+  out_path = test.built_file_path(path, chdir='src')
+
+  in_stat = os.stat(os.path.join('src', path))
+  out_stat = os.stat(out_path)
+  if out_stat.st_mode & stat.S_IXUSR != expected_exec_bit:
+    test.fail_test()
+
+
+test = TestGyp.TestGyp()
+
+test.run_gyp('copies-attribs.gyp', chdir='src')
+
+test.build('copies-attribs.gyp', chdir='src')
+
+if sys.platform != 'win32':
+  out_path = test.built_file_path('executable-file.sh', chdir='src')
+  test.must_contain(out_path,
+                    '#!/bin/bash\n'
+                    '\n'
+                    'echo echo echo echo cho ho o o\n')
+  check_attribs('executable-file.sh', expected_exec_bit=stat.S_IXUSR)
+
+test.pass_test()
diff --git a/test/copies/src/copies-attribs.gyp b/test/copies/src/copies-attribs.gyp
new file mode 100644
index 0000000..073e0d0
--- /dev/null
+++ b/test/copies/src/copies-attribs.gyp
@@ -0,0 +1,20 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'targets': [
+    {
+      'target_name': 'copies1',
+      'type': 'none',
+      'copies': [
+        {
+          'destination': '<(PRODUCT_DIR)',
+          'files': [
+            'executable-file.sh',
+          ],
+        },
+      ],
+    },
+  ],
+}
diff --git a/test/copies/src/executable-file.sh b/test/copies/src/executable-file.sh
new file mode 100755
index 0000000..796953a
--- /dev/null
+++ b/test/copies/src/executable-file.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+echo echo echo echo cho ho o o
diff --git a/test/mac/bundle-resources/executable-file.sh b/test/mac/bundle-resources/executable-file.sh
new file mode 100755
index 0000000..796953a
--- /dev/null
+++ b/test/mac/bundle-resources/executable-file.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+echo echo echo echo cho ho o o
diff --git a/test/mac/bundle-resources/test.gyp b/test/mac/bundle-resources/test.gyp
index 86cd26b..af034ce 100644
--- a/test/mac/bundle-resources/test.gyp
+++ b/test/mac/bundle-resources/test.gyp
@@ -9,6 +9,7 @@
       'mac_bundle': 1,
       'mac_bundle_resources': [
         'secret.txt',
+        'executable-file.sh',
       ],
     },
     # A rule with process_outputs_as_mac_bundle_resources should copy files
diff --git a/test/mac/gyptest-bundle-resources.py b/test/mac/gyptest-bundle-resources.py
index 7d2f9d0..824b17f 100644
--- a/test/mac/gyptest-bundle-resources.py
+++ b/test/mac/gyptest-bundle-resources.py
@@ -10,8 +10,23 @@
 
 import TestGyp
 
+import os
+import stat
 import sys
 
+
+def check_attribs(path, expected_exec_bit):
+  out_path = test.built_file_path(
+      os.path.join('resource.app/Contents/Resources', path), chdir=CHDIR)
+
+  in_stat = os.stat(os.path.join(CHDIR, path))
+  out_stat = os.stat(out_path)
+  if in_stat.st_mtime == out_stat.st_mtime:
+    test.fail_test()
+  if out_stat.st_mode & stat.S_IXUSR != expected_exec_bit:
+    test.fail_test()
+
+
 if sys.platform == 'darwin':
   # set |match| to ignore build stderr output.
   test = TestGyp.TestGyp(formats=['ninja', 'make', 'xcode'])
@@ -26,6 +41,15 @@
   test.built_file_must_match('source_rule.app/Contents/Resources/secret.txt',
                              'ABC\n', chdir=CHDIR)
 
+  test.built_file_must_match(
+      'resource.app/Contents/Resources/executable-file.sh',
+      '#!/bin/bash\n'
+      '\n'
+      'echo echo echo echo cho ho o o\n', chdir=CHDIR)
+
+  check_attribs('executable-file.sh', expected_exec_bit=stat.S_IXUSR)
+  check_attribs('secret.txt', expected_exec_bit=0)
+
   # TODO(thakis): This currently fails with make.
   if test.format != 'make':
     test.built_file_must_match(