util: add new set_flags method
authorMatt Mackall <mpm@selenic.com>
Thu, 27 Dec 2007 22:27:45 -0600
changeset 5702 1b914de8d0ba
parent 5701 32c2832682a9
child 5703 14789f30ac11
util: add new set_flags method This is more efficient than calling set_link and set_exec
mercurial/util.py
--- a/mercurial/util.py	Thu Dec 27 22:27:43 2007 -0600
+++ b/mercurial/util.py	Thu Dec 27 22:27:45 2007 -0600
@@ -991,6 +991,9 @@
     def set_link(f, mode):
         pass
 
+    def set_flags(f, flags):
+        pass
+
     def set_binary(fd):
         msvcrt.setmode(fd.fileno(), os.O_BINARY)
 
@@ -1174,6 +1177,34 @@
             os.unlink(f)
             file(f, "w").write(data)
 
+    def set_flags(f, flags):
+        s = os.lstat(f).st_mode
+        x = "x" in flags
+        l = "l" in flags
+        if l:
+            if not stat.S_ISLNK(s):
+                # switch file to link
+                data = file(f).read()
+                os.unlink(f)
+                os.symlink(data, f)
+            # no chmod needed at this point
+            return
+        if stat.S_ISLNK(s):
+            # switch link to file
+            data = os.readlink(f)
+            os.unlink(f)
+            file(f, "w").write(data)
+            s = 0666 & ~_umask # avoid restatting for chmod
+
+        sx = s & 0100
+        if x and not sx:
+            # Turn on +x for every +r bit when making a file executable
+            # and obey umask.
+            os.chmod(f, s | (s & 0444) >> 2 & ~_umask)
+        elif not x and sx:
+            # Turn off all +x bits
+            os.chmod(f, s & 0666)
+
     def set_binary(fd):
         pass