inherit mode patch

Alexis S. L. Carvalho alexis at cecm.usp.br
Sun Mar 4 09:30:42 CST 2007


Hi

I was thinking of (finally) pushing some version of Aurelian Jacobs's
patch to make new files under .hg inherit the permissions from the .hg
directory itself - specifically the version below[1], slightly updated
to take advantadge of the fact that we now cache the value of umask in
util.py

As he mentions in the original message, to create N files, this patch
needs:

     - 1 stat() if N > 0
     - N chmod() only if needed (ie. if current umask is not enough)

I'm slightly worried about effects of this patch on windows -
specifically, is the return of os.umask() sane and can we do operations
like the below:

repomode = os.lstat(repo.root).st_mode
repomode & os.umask() # check if we have to call chmod
os.chmod(newdir, repomode)
os.chmod(newfile, repomode & 0666)

Alexis

[1] - from this message: 
http://www.selenic.com/pipermail/mercurial-devel/2006-November/000147.html



# HG changeset patch
# User Aurelien Jacobs <aurel at gnuage.org>
# Date 1162423036 -3600
# Node ID ef1b3ed0db47a6f87f85bb93b746a6ac595ad4fb
# Parent  9383af6f236d1e9c5dcbc7d9b6145adb1aff0eb8
inherit .hg mode when creating new file

diff -r 9383af6f236d -r ef1b3ed0db47 mercurial/localrepo.py
--- a/mercurial/localrepo.py	Wed Oct 25 18:45:18 2006 +0200
+++ b/mercurial/localrepo.py	Thu Nov 02 00:17:16 2006 +0100
@@ -47,7 +47,7 @@ class localrepository(repo.repository):
         self.origroot = path
         self.ui = ui.ui(parentui=parentui)
         self.opener = util.opener(self.path)
-        self.sopener = util.opener(self.path)
+        self.sopener = util.opener(self.path, inherit_mode=True)
         self.wopener = util.opener(self.root)
 
         try:
diff -r 9383af6f236d -r ef1b3ed0db47 mercurial/util.py
--- a/mercurial/util.py	Wed Oct 25 18:45:18 2006 +0200
+++ b/mercurial/util.py	Thu Nov 02 00:17:16 2006 +0100
@@ -719,7 +719,7 @@ else:
             return _("stopped by signal %d") % val, val
         raise ValueError(_("invalid exit code"))
 
-def opener(base, audit=True):
+def opener(base, inherit_mode=False, audit=True):
     """
     return a function that opens files relative to base
 
@@ -728,6 +728,7 @@ def opener(base, audit=True):
     """
     p = base
     audit_p = audit
+    w_mode = inherit_mode
 
     def mktempcopy(name):
         d, fn = os.path.split(name)
@@ -753,6 +754,30 @@ def opener(base, audit=True):
         os.chmod(temp, st.st_mode)
         return temp
 
+    def get_write_mode(path):
+        mode = os.stat(path).st_mode
+        umask = os.umask(0)
+        os.umask(umask)
+        if umask & mode:
+            return mode
+        return None
+
+    def makedirs(name, repo_mode=None):
+        """recursive directory creation with parent mode inheritance"""
+        parent = os.path.abspath(os.path.dirname(name))
+        try:
+            os.mkdir(name)
+            if repo_mode is not None:
+                os.chmod(name, repo_mode)
+            return
+        except OSError, err:
+            if err.errno == errno.EEXIST:
+                return
+            if err.errno != errno.ENOENT:
+                raise
+        makedirs(parent)
+        makedirs(name)
+
     class atomictempfile(posixfile):
         """the file will only be copied when rename is called"""
         def __init__(self, name, mode):
@@ -783,6 +808,9 @@ def opener(base, audit=True):
         if audit_p:
             audit_path(path)
         f = os.path.join(p, path)
+        st_mode = None
+        if not "repo_mode" in dir(o):
+            o.repo_mode = None
 
         if not text:
             mode += "b" # for that other OS
@@ -791,9 +819,13 @@ def opener(base, audit=True):
             try:
                 nlink = nlinks(f)
             except OSError:
+                if w_mode and o.repo_mode is None:
+                    o.repo_mode = get_write_mode(p)
                 d = os.path.dirname(f)
                 if not os.path.isdir(d):
-                    os.makedirs(d)
+                    makedirs(d, o.repo_mode)
+                if o.repo_mode is not None:
+                    st_mode = o.repo_mode & 0666
             else:
                 if atomic:
                     return atomicfile(f, mode)
@@ -801,7 +833,10 @@ def opener(base, audit=True):
                     return atomictempfile(f, mode)
                 if nlink > 1:
                     rename(mktempcopy(f), f)
-        return posixfile(f, mode)
+        pf = posixfile(f, mode)
+        if st_mode is not None:
+            os.chmod(f, st_mode)
+        return pf
 
     return o
 


More information about the Mercurial-devel mailing list