[PATCH] osutil.c for Win32 - take 2 - the patch is now integrated into main osutil.c - no other files are required and more of the stat structure and code is reused

Petr Kodl petrkodl at gmail.com
Wed Sep 3 20:23:17 UTC 2008


# HG changeset patch
# User Petr Kodl<petrkodl at gmail.com>
# Date 1220473188 14400
# Node ID 1d4672f2e6d68e724b275eaa3d3de6dc9b9df573
# Parent  6c4a08270222569ba906f4f1c7860783eec19225
osutil.c implementation for Win32

diff -r 6c4a08270222 -r 1d4672f2e6d6 mercurial/osutil.c
--- a/mercurial/osutil.c    Wed Sep 03 19:03:57 2008 +0200
+++ b/mercurial/osutil.c    Wed Sep 03 16:19:48 2008 -0400
@@ -7,18 +7,45 @@
  the GNU General Public License, incorporated herein by reference.
 */

-#define _ATFILE_SOURCE
-#include <Python.h>
+#define _ATFILE_SOURCE
+
+#include <Python.h>
+#include <string.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#else
 #include <dirent.h>
 #include <fcntl.h>
 #include <string.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
+#endif
+
+#ifdef _WIN32
+/*
+minimal stat struct compatible with hg expectations
+supporting large files (64 bit size)
+*/
+struct non_posix_stat
+{
+    int     st_dev;
+    int     st_mode;
+    int     st_nlink;
+    __int64 st_size;
+    int     st_mtime;
+    int     st_ctime;
+};
+typedef struct non_posix_stat my_stat;
+#else
+typedef struct stat my_stat;
+#endif
+

 struct listdir_stat {
     PyObject_HEAD
-    struct stat st;
+    my_stat st;
 };

 #define listdir_slot(name) \
@@ -30,9 +57,16 @@
 listdir_slot(st_dev)
 listdir_slot(st_mode)
 listdir_slot(st_nlink)
-listdir_slot(st_size)
 listdir_slot(st_mtime)
 listdir_slot(st_ctime)
+#ifdef _WIN32
+static PyObject *listdir_stat_st_size(PyObject *self, void *x)
+{
+    return PyLong_FromLongLong((PY_LONG_LONG)((struct listdir_stat
*)self)->st.st_size);
+}
+#else
+listdir_slot(st_size)
+#endif

 static struct PyGetSetDef listdir_stat_getsets[] = {
     {"st_dev", listdir_stat_st_dev, 0, 0, 0},
@@ -95,6 +129,117 @@
     0,                         /* tp_alloc */
     listdir_stat_new,          /* tp_new */
 };
+
+#ifdef _WIN32
+
+static __int64 a0 =
(__int64)134774L*(__int64)24L*(__int64)3600L*(__int64)1000L*(__int64)1000L*(__int64)10L;
+static __int64 a1 = 1000*1000*10;
+
+static int to_python_time(FILETIME* ms_time)
+{
+    __int64 tmp;
+    memcpy(&tmp,ms_time,sizeof(__int64));
+    return (int)((tmp-a0)/a1);
+}
+
+static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+    static char *kwlist[] = { "path", "stat", NULL };
+    PyObject *list        = NULL;
+    PyObject* item        = NULL;
+    PyObject *py_st       = NULL;
+    PyObject *statobj     = NULL;
+    PyObject *ctor_args   = PyTuple_New(0);
+    struct non_posix_stat* stp = 0;
+    char  *path;
+    int   path_len;
+    int   keep_stat;
+    WIN32_FIND_DATA fd;
+    HANDLE  fh=NULL;
+    char full_path[_MAX_PATH+10];
+
+
if(!PyArg_ParseTupleAndKeywords(args,kwargs,"s#|O:listdir",kwlist,&path,&path_len,&statobj))
+        goto end;
+
+    keep_stat = statobj && PyObject_IsTrue(statobj);
+
+    strncpy(full_path,path,path_len);
+    strncpy(full_path+path_len,"\\*.*",5);
+
+    fh = FindFirstFile(full_path,&fd);
+    if(INVALID_HANDLE_VALUE!=fh)
+    {
+        list = PyList_New(0);
+        if(!list)
+        {
+            PyErr_NoMemory();
+            goto end;
+        }
+        do
+        {
+            int isdir = (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
+            int isro  = (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY);
+            if(!isdir || (strcmp(fd.cFileName,".") &&
strcmp(fd.cFileName,"..") && strcmp(fd.cFileName,".hg")))
+            {
+                PyObject* item = PyTuple_New(keep_stat ? 3 : 2);
+                if(!item)
+                {
+                    PyErr_NoMemory();
+                    goto end;
+                }
+                PyTuple_SetItem(item,0,PyString_FromString(fd.cFileName));
+                PyTuple_SetItem(item,1,PyInt_FromLong(isdir ? _S_IFDIR :
_S_IFREG));
+                if(keep_stat)
+                {
+                    py_st = PyObject_CallObject((PyObject
*)&listdir_stat_type,ctor_args);
+                    if(!py_st)
+                    {
+                        PyErr_NoMemory();
+                        goto end;
+                    }
+                    stp = &((struct listdir_stat *)py_st)->st;
+                    stp->st_mtime = to_python_time(&fd.ftLastWriteTime);
+                    stp->st_ctime = to_python_time(&fd.ftCreationTime);
+                    stp->st_dev   = 0;
+                    stp->st_size  = 0;
+                    stp->st_mode  = (isdir ? (S_IFDIR | 0111) : S_IFREG) |
(isro ? 0444 : 0666);
+                    if(!isdir)
+                    {
+                        char* dot = strrchr(fd.cFileName,'.');
+                        if (dot)
+                        {
+                            if(     !stricmp(dot,".bat")
+                                ||  !stricmp(dot,".cmd")
+                                ||  !stricmp(dot,".exe")
+                                ||  !stricmp(dot,".com"))
+                            stp->st_mode |= 0111;
+                        }
+                        stp->st_size = (__int64)(fd.nFileSizeHigh<<32) +
fd.nFileSizeLow;
+                    }
+                    PyTuple_SetItem(item,2,py_st);
+                    py_st = NULL;
+                }
+                PyList_Append(list,item);
+                Py_XDECREF(item);
+                item=NULL;
+            }
+        }
+        while(FindNextFile(fh,&fd));
+        FindClose(fh);
+    }
+    else
+    {
+
PyErr_SetExcFromWindowsErrWithFilename(PyExc_OSError,GetLastError(),path);
+    }
+end:
+    Py_XDECREF(ctor_args);
+    Py_XDECREF(item);
+    Py_XDECREF(py_st);
+    if(list) PyList_Sort(list);
+    return list;
+}
+
+#else

 static PyObject *listfiles(PyObject *list, DIR *dir,
                int keep_stat, int *need_stat)
@@ -295,7 +440,7 @@
         closedir(dir);
     return err ? err : list;
 }
-
+#endif

 static char osutil_doc[] = "Native operating system services.";

diff -r 6c4a08270222 -r 1d4672f2e6d6 setup.py
--- a/setup.py    Wed Sep 03 19:03:57 2008 +0200
+++ b/setup.py    Wed Sep 03 16:19:48 2008 -0400
@@ -101,9 +101,10 @@
 packages = ['mercurial', 'mercurial.hgweb', 'hgext', 'hgext.convert',
             'hgext.highlight']

+ext_modules.append(Extension('mercurial.osutil', ['mercurial/osutil.c']))
+
 try:
     import posix
-    ext_modules.append(Extension('mercurial.osutil',
['mercurial/osutil.c']))

     if sys.platform == 'linux2' and os.uname()[2] > '2.6':
         # The inotify extension is only usable with Linux 2.6 kernels.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurial-scm.org/pipermail/mercurial-devel/attachments/20080903/80ce4d13/attachment.html>


More information about the Mercurial-devel mailing list