inherit mode patch

Alexis S. L. Carvalho alexis at cecm.usp.br
Sun Mar 4 10:12:23 CST 2007


Thus spake Alexis S. L. Carvalho:
> 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

Below is a patch that actually applies and (I think) works.  There's
still a small issue that the .hg/store/{journal,undo} files created by
the transaction system still follow the umask, but that can be solved
later.

Hmm...  I guess I'll have to fix the directory creation for symlinks
that I pushed earlier today, too...

Alexis


diff -r 26596a6b6518 -r 0f320bf33473 mercurial/localrepo.py
--- a/mercurial/localrepo.py	Fri Feb 23 17:54:34 2007 +0200
+++ b/mercurial/localrepo.py	Thu Nov 02 00:17:16 2006 +0100
@@ -33,7 +33,7 @@ class localrepository(repo.repository):
         self.path = os.path.join(path, ".hg")
         self.root = os.path.realpath(path)
         self.origroot = path
-        self.opener = util.opener(self.path)
+        self.opener = util.opener(self.path, inheritmode=True)
         self.wopener = util.opener(self.root)
 
         if not os.path.isdir(self.path):
@@ -78,7 +78,9 @@ class localrepository(repo.repository):
             self.encodefn = lambda x: x
             self.decodefn = lambda x: x
             self.spath = self.path
-        self.sopener = util.encodedopener(util.opener(self.spath), self.encodefn)
+        self.sopener = util.encodedopener(util.opener(self.spath,
+                                                      inheritmode=True),
+                                          self.encodefn)
 
         self.ui = ui.ui(parentui=parentui)
         try:
diff -r 26596a6b6518 -r 0f320bf33473 mercurial/util.py
--- a/mercurial/util.py	Fri Feb 23 17:54:34 2007 +0200
+++ b/mercurial/util.py	Thu Nov 02 00:17:16 2006 +0100
@@ -764,6 +764,9 @@ def linkfunc(path, fallback):
         return lambda x: is_link(os.path.join(path, x))
     return fallback
 
+_umask = os.umask(0)
+os.umask(_umask)
+
 # Platform specific variants
 if os.name == 'nt':
     import msvcrt
@@ -890,8 +893,6 @@ if os.name == 'nt':
 
 else:
     nulldev = '/dev/null'
-    _umask = os.umask(0)
-    os.umask(_umask)
 
     def rcfiles(path):
         rcs = [os.path.join(path, 'hgrc')]
@@ -1057,7 +1058,7 @@ def encodedopener(openerfn, fn):
         return openerfn(fn(path), *args, **kw)
     return o
 
-def opener(base, audit=True):
+def opener(base, inheritmode=False, audit=True):
     """
     return a function that opens files relative to base
 
@@ -1066,6 +1067,11 @@ def opener(base, audit=True):
     """
     p = base
     audit_p = audit
+    class namespace(object):
+        pass
+    ns = namespace()
+    ns.wmode = inheritmode
+    ns.repomode = None
 
     def mktempcopy(name):
         d, fn = os.path.split(name)
@@ -1091,6 +1097,28 @@ def opener(base, audit=True):
         os.chmod(temp, st.st_mode)
         return temp
 
+    def get_write_mode(path):
+        mode = os.stat(path).st_mode
+        if (0777 & ~_umask) != (0777 & 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):
@@ -1121,6 +1149,7 @@ def opener(base, audit=True):
         if audit_p:
             audit_path(path)
         f = os.path.join(p, path)
+        st_mode = None
 
         if not text:
             mode += "b" # for that other OS
@@ -1129,9 +1158,14 @@ def opener(base, audit=True):
             try:
                 nlink = nlinks(f)
             except OSError:
+                if ns.wmode:
+                    ns.repomode = get_write_mode(p)
+                    ns.wmode = False
                 d = os.path.dirname(f)
                 if not os.path.isdir(d):
-                    os.makedirs(d)
+                    makedirs(d, ns.repomode)
+                if ns.repomode is not None:
+                    st_mode = ns.repomode & 0666
             else:
                 if atomic:
                     return atomicfile(f, mode)
@@ -1139,7 +1173,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