##// END OF EJS Templates
findcopies: fix rename bug...
findcopies: fix rename bug We've fiddled with this line several times, and an old bug has reappeared from it. Let's take a peek at the history. The original "or" (rev 3674, in 0.9.2 and 0.9.3): http://www.selenic.com/hg/rev/9103dab96093 Then I changed it to an "and" to fix a bug (rev 4304): http://www.selenic.com/hg/rev/4787e2b0dd03 Then for reasons now lost in the mists of time, I dropped half (rev 4399): http://www.selenic.com/hg/rev/93652499bed3 Then we added back the "or" (rev 4416, in 0.9.4): http://www.selenic.com/hg/rev/bb1800a7d7e1 So it seems it ought to be "and".

File last commit:

r5428:eb1b6aae default
r5429:77cafe8f default
Show More
osutil.c
307 lines | 7.4 KiB | text/x-c | CLexer
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 /*
osutil.c - native operating system services
Copyright 2007 Matt Mackall and others
This software may be used and distributed according to the terms of
the GNU General Public License, incorporated herein by reference.
*/
#define _ATFILE_SOURCE
Alexis S. L. Carvalho
osutil.c: include Python.h before the other headers...
r5397 #include <Python.h>
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 #include <alloca.h>
#include <dirent.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
struct listdir_stat {
Matt Mackall
osutil: cleanups...
r5421 PyObject_HEAD
struct stat st;
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 };
#define listdir_slot(name) \
static PyObject *listdir_stat_##name(PyObject *self, void *x) \
{ \
Matt Mackall
osutil: cleanups...
r5421 return PyInt_FromLong(((struct listdir_stat *)self)->st.name); \
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 }
listdir_slot(st_dev);
listdir_slot(st_mode);
listdir_slot(st_nlink);
listdir_slot(st_size);
listdir_slot(st_mtime);
listdir_slot(st_ctime);
static struct PyGetSetDef listdir_stat_getsets[] = {
Matt Mackall
osutil: cleanups...
r5421 {"st_dev", listdir_stat_st_dev, 0, 0, 0},
{"st_mode", listdir_stat_st_mode, 0, 0, 0},
{"st_nlink", listdir_stat_st_nlink, 0, 0, 0},
{"st_size", listdir_stat_st_size, 0, 0, 0},
{"st_mtime", listdir_stat_st_mtime, 0, 0, 0},
{"st_ctime", listdir_stat_st_ctime, 0, 0, 0},
{0, 0, 0, 0, 0}
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 };
static PyObject *listdir_stat_new(PyTypeObject *t, PyObject *a, PyObject *k)
{
Matt Mackall
osutil: cleanups...
r5421 return t->tp_alloc(t, 0);
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 }
static void listdir_stat_dealloc(PyObject *o)
{
Matt Mackall
osutil: cleanups...
r5421 o->ob_type->tp_free(o);
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 }
static PyTypeObject listdir_stat_type = {
Matt Mackall
osutil: cleanups...
r5421 PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"osutil.stat", /*tp_name*/
sizeof(struct listdir_stat), /*tp_basicsize*/
0, /*tp_itemsize*/
(destructor)listdir_stat_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash */
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
"stat objects", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
listdir_stat_getsets, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
listdir_stat_new, /* tp_new */
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 };
static inline int mode_to_kind(int mode)
{
Matt Mackall
osutil: cleanups...
r5421 if (S_ISREG(mode)) return S_IFREG;
if (S_ISDIR(mode)) return S_IFDIR;
if (S_ISLNK(mode)) return S_IFLNK;
if (S_ISBLK(mode)) return S_IFBLK;
if (S_ISCHR(mode)) return S_IFCHR;
if (S_ISFIFO(mode)) return S_IFIFO;
if (S_ISSOCK(mode)) return S_IFSOCK;
return mode;
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 }
Matt Mackall
osutil: more tidying...
r5428 static PyObject *listfiles(PyObject *list, DIR *dir,
int keep_stat, int *need_stat)
Matt Mackall
osutil: move file list loop to its own function
r5427 {
struct dirent *ent;
PyObject *name, *py_kind, *val;
Matt Mackall
osutil: more tidying...
r5428 #ifdef DT_REG
*need_stat = 0;
#else
*need_stat = 1;
#endif
Matt Mackall
osutil: move file list loop to its own function
r5427 for (ent = readdir(dir); ent; ent = readdir(dir)) {
int kind = -1;
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
continue;
#ifdef DT_REG
Matt Mackall
osutil: more tidying...
r5428 if (!keep_stat)
Matt Mackall
osutil: move file list loop to its own function
r5427 switch (ent->d_type) {
case DT_REG: kind = S_IFREG; break;
case DT_DIR: kind = S_IFDIR; break;
case DT_LNK: kind = S_IFLNK; break;
case DT_BLK: kind = S_IFBLK; break;
case DT_CHR: kind = S_IFCHR; break;
case DT_FIFO: kind = S_IFIFO; break;
case DT_SOCK: kind = S_IFSOCK; break;
default:
Matt Mackall
osutil: more tidying...
r5428 *need_stat = 0;
Matt Mackall
osutil: move file list loop to its own function
r5427 break;
}
#endif
if (kind != -1)
py_kind = PyInt_FromLong(kind);
else {
py_kind = Py_None;
Py_INCREF(Py_None);
}
Matt Mackall
osutil: more tidying...
r5428 val = PyTuple_New(keep_stat ? 3 : 2);
Matt Mackall
osutil: move file list loop to its own function
r5427 name = PyString_FromString(ent->d_name);
if (!name || !py_kind || !val) {
Py_XDECREF(name);
Py_XDECREF(py_kind);
Py_XDECREF(val);
return PyErr_NoMemory();
}
PyTuple_SET_ITEM(val, 0, name);
PyTuple_SET_ITEM(val, 1, py_kind);
Matt Mackall
osutil: more tidying...
r5428 if (keep_stat) {
Matt Mackall
osutil: move file list loop to its own function
r5427 PyTuple_SET_ITEM(val, 2, Py_None);
Py_INCREF(Py_None);
}
PyList_Append(list, val);
Py_DECREF(val);
}
return 0;
}
Matt Mackall
osutils: pull file stat loop into its own function
r5425 static PyObject *statfiles(PyObject *list, PyObject *ctor_args, int keep,
char *path, int len, DIR *dir)
{
struct stat buf;
struct stat *stp = &buf;
int kind;
int ret;
ssize_t i;
ssize_t size = PyList_Size(list);
#ifdef AT_SYMLINK_NOFOLLOW
int dfd = dirfd(dir);
#endif
for (i = 0; i < size; i++) {
PyObject *elt = PyList_GetItem(list, i);
char *name = PyString_AsString(PyTuple_GET_ITEM(elt, 0));
PyObject *py_st = NULL;
PyObject *py_kind = PyTuple_GET_ITEM(elt, 1);
kind = py_kind == Py_None ? -1 : PyInt_AsLong(py_kind);
if (kind != -1 && !keep)
continue;
strncat(path + len + 1, name, PATH_MAX - len);
path[PATH_MAX] = 0;
if (keep) {
py_st = PyObject_CallObject(
(PyObject *)&listdir_stat_type, ctor_args);
if (!py_st)
return PyErr_NoMemory();
stp = &((struct listdir_stat *)py_st)->st;
PyTuple_SET_ITEM(elt, 2, py_st);
}
#ifdef AT_SYMLINK_NOFOLLOW
ret = fstatat(dfd, name, stp, AT_SYMLINK_NOFOLLOW);
#else
ret = lstat(path, stp);
#endif
if (ret == -1)
return PyErr_SetFromErrnoWithFilename(PyExc_OSError,
path);
if (kind == -1)
kind = mode_to_kind(stp->st_mode);
if (py_kind == Py_None && kind != -1) {
py_kind = PyInt_FromLong(kind);
if (!py_kind)
return PyErr_NoMemory();
Py_XDECREF(Py_None);
PyTuple_SET_ITEM(elt, 1, py_kind);
}
}
return 0;
}
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs)
{
Giorgos Keramidas
osutil.c: style fix - delete trailing end-of-line spaces
r5416 static char *kwlist[] = { "path", "stat", NULL };
Matt Mackall
osutil: more tidying...
r5428 DIR *dir = NULL;
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 PyObject *statobj = NULL;
Matt Mackall
osutil: cleanups...
r5421 PyObject *list = NULL;
Matt Mackall
osutils: pull file stat loop into its own function
r5425 PyObject *err = NULL;
Matt Mackall
osutil: cleanups...
r5421 PyObject *ctor_args = NULL;
Matt Mackall
osutil: more tidying...
r5428 char *path;
Matt Mackall
osutil: eliminate alloca call...
r5422 char full_path[PATH_MAX + 10];
Matt Mackall
osutil: cleanups...
r5421 int path_len;
Matt Mackall
osutil: more tidying...
r5428 int need_stat, keep_stat;
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|O:listdir", kwlist,
&path, &path_len, &statobj))
Matt Mackall
osutil: cleanups...
r5421 goto bail;
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
Matt Mackall
osutil: more tidying...
r5428 keep_stat = statobj && PyObject_IsTrue(statobj);
Giorgos Keramidas
osutil.c: style fix - delete trailing end-of-line spaces
r5416
Matt Mackall
osutil: cleanups...
r5421 dir = opendir(path);
if (!dir) {
Matt Mackall
osutil: more tidying...
r5428 err = PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
Matt Mackall
osutil: cleanups...
r5421 goto bail;
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 }
Matt Mackall
osutil: cleanups...
r5421 list = PyList_New(0);
Matt Mackall
osutil: more tidying...
r5428 ctor_args = PyTuple_New(0);
if (!list || !ctor_args)
Matt Mackall
osutil: cleanups...
r5421 goto bail;
Giorgos Keramidas
osutil.c: style fix - delete trailing end-of-line spaces
r5416
Matt Mackall
osutil: eliminate alloca call...
r5422 strncpy(full_path, path, PATH_MAX);
Matt Mackall
osutil: cleanups...
r5421 full_path[path_len] = '/';
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
Matt Mackall
osutil: more tidying...
r5428 err = listfiles(list, dir, keep_stat, &need_stat);
Matt Mackall
osutil: move file list loop to its own function
r5427 if (err)
goto bail;
Matt Mackall
osutil: cleanups...
r5421
PyList_Sort(list);
Matt Mackall
osutil: more tidying...
r5428 if (!keep_stat && !need_stat)
goto done;
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
Matt Mackall
osutil: more tidying...
r5428 err = statfiles(list, ctor_args, keep_stat, full_path, path_len, dir);
if (!err)
goto done;
Matt Mackall
osutil: cleanups...
r5421
Matt Mackall
osutil: more cleanups...
r5423 bail:
Py_XDECREF(list);
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
Matt Mackall
osutil: more cleanups...
r5423 done:
Py_XDECREF(ctor_args);
if (dir)
closedir(dir);
Matt Mackall
osutils: pull file stat loop into its own function
r5425 return err ? err : list;
Matt Mackall
osutil: cleanups...
r5421 }
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
static char osutil_doc[] = "Native operating system services.";
static PyMethodDef methods[] = {
Matt Mackall
osutil: cleanups...
r5421 {"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
"list a directory\n"},
{NULL, NULL}
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 };
PyMODINIT_FUNC initosutil(void)
{
Matt Mackall
osutil: cleanups...
r5421 if (PyType_Ready(&listdir_stat_type) == -1)
return;
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396
Matt Mackall
osutil: cleanups...
r5421 Py_InitModule3("osutil", methods, osutil_doc);
Bryan O'Sullivan
Add osutil module, containing a listdir function....
r5396 }