mercurial/cext/dirs.c
author Gregory Szorc <gregory.szorc@gmail.com>
Mon, 20 Jan 2020 23:51:25 -0800
changeset 44118 f81c17ec303c
parent 43838 a47ccdcce4f9
child 47539 84391ddf4c78
permissions -rw-r--r--
hgdemandimport: apply lazy module loading to sys.meta_path finders Python's `sys.meta_path` finders are the primary objects whose job it is to find a module at import time. When `import` is called, Python iterates objects in this list and calls `o.find_spec(...)` to find a `ModuleSpec` (or None if the module couldn't be found by that finder). If no meta path finder can find a module, import fails. One of the default meta path finders is `PathFinder`. Its job is to import modules from the filesystem and is probably the most important importer. This finder looks at `sys.path` and `sys.path_hooks` to do its job. The `ModuleSpec` returned by `MetaPathImporter.find_spec()` has a `loader` attribute, which defines the concrete module loader to use. `sys.path_hooks` is a hook point for teaching `PathFinder` to instantiate custom loader types. Previously, we injected a custom `sys.path_hook` that told `PathFinder` to wrap the default loaders with a loader that creates a module object that is lazy. This approach worked. But its main limitation was that it only applied to the `PathFinder` meta path importer. There are other meta path importers that are registered. And in the case of PyOxidizer loading modules from memory, `PathFinder` doesn't come into play since PyOxidizer's own meta path importer was handling all imports. This commit changes our approach to lazy module loading by proxying all meta path importers. Specifically, we overload the `find_spec()` method to swap in a wrapped loader on the `ModuleSpec` before it is returned. The end result of this is all meta path importers should be lazy. As much as I would have loved to utilize .__class__ manipulation to achieve this, some meta path importers are implemented in C/Rust in such a way that they cannot be monkeypatched. This is why we use __getattribute__ to define a proxy. Also, this change could theoretically open us up to regressions in meta path importers whose loader is creating module objects which can't be monkeypatched. But I'm not aware of any of these in the wild. So I think we'll be safe. According to hyperfine, this change yields a decent startup time win of 5-6ms: ``` Benchmark #1: ~/.pyenv/versions/3.6.10/bin/python ./hg version Time (mean ± σ): 86.8 ms ± 0.5 ms [User: 78.0 ms, System: 8.7 ms] Range (min … max): 86.0 ms … 89.1 ms 50 runs Time (mean ± σ): 81.1 ms ± 2.7 ms [User: 74.5 ms, System: 6.5 ms] Range (min … max): 77.8 ms … 90.5 ms 50 runs Benchmark #2: ~/.pyenv/versions/3.7.6/bin/python ./hg version Time (mean ± σ): 78.9 ms ± 0.6 ms [User: 70.2 ms, System: 8.7 ms] Range (min … max): 78.1 ms … 81.2 ms 50 runs Time (mean ± σ): 73.4 ms ± 0.6 ms [User: 65.3 ms, System: 8.0 ms] Range (min … max): 72.4 ms … 75.7 ms 50 runs Benchmark #3: ~/.pyenv/versions/3.8.1/bin/python ./hg version Time (mean ± σ): 78.1 ms ± 0.6 ms [User: 70.2 ms, System: 7.9 ms] Range (min … max): 77.4 ms … 80.9 ms 50 runs Time (mean ± σ): 72.1 ms ± 0.4 ms [User: 64.4 ms, System: 7.6 ms] Range (min … max): 71.4 ms … 74.1 ms 50 runs ``` Differential Revision: https://phab.mercurial-scm.org/D7954
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
     1
/*
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
     2
 dirs.c - dynamic directory diddling for dirstates
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
     3
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
     4
 Copyright 2013 Facebook
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
     5
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
     6
 This software may be used and distributed according to the terms of
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
     7
 the GNU General Public License, incorporated herein by reference.
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
     8
*/
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
     9
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    10
#define PY_SSIZE_T_CLEAN
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    11
#include <Python.h>
43658
0796e266d26b dirs: resolve fuzzer OOM situation by disallowing deep directory hierarchies
Augie Fackler <augie@google.com>
parents: 43494
diff changeset
    12
#include <string.h>
34438
b90e8da190da cext: reorder #include
Gregory Szorc <gregory.szorc@gmail.com>
parents: 32372
diff changeset
    13
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    14
#include "util.h"
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    15
30106
cb3048746dae dirs: port PyInt code to work on Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30105
diff changeset
    16
#ifdef IS_PY3K
43838
a47ccdcce4f9 dirs: fix out-of-bounds access in Py3
Martin von Zweigbergk <martinvonz@google.com>
parents: 43658
diff changeset
    17
#define PYLONG_VALUE(o) ((PyLongObject *)o)->ob_digit[0]
30106
cb3048746dae dirs: port PyInt code to work on Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30105
diff changeset
    18
#else
cb3048746dae dirs: port PyInt code to work on Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30105
diff changeset
    19
#define PYLONG_VALUE(o) PyInt_AS_LONG(o)
cb3048746dae dirs: port PyInt code to work on Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30105
diff changeset
    20
#endif
cb3048746dae dirs: port PyInt code to work on Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30105
diff changeset
    21
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    22
/*
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    23
 * This is a multiset of directory names, built from the files that
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    24
 * appear in a dirstate or manifest.
18901
66d3aebe2d95 dirs: use mutable integers internally
Bryan O'Sullivan <bryano@fb.com>
parents: 18900
diff changeset
    25
 *
66d3aebe2d95 dirs: use mutable integers internally
Bryan O'Sullivan <bryano@fb.com>
parents: 18900
diff changeset
    26
 * A few implementation notes:
66d3aebe2d95 dirs: use mutable integers internally
Bryan O'Sullivan <bryano@fb.com>
parents: 18900
diff changeset
    27
 *
66d3aebe2d95 dirs: use mutable integers internally
Bryan O'Sullivan <bryano@fb.com>
parents: 18900
diff changeset
    28
 * We modify Python integers for refcounting, but those integers are
66d3aebe2d95 dirs: use mutable integers internally
Bryan O'Sullivan <bryano@fb.com>
parents: 18900
diff changeset
    29
 * never visible to Python code.
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    30
 */
43232
be178b5d91c8 dirs: tag a struct as not being formattable
Augie Fackler <augie@google.com>
parents: 43229
diff changeset
    31
/* clang-format off */
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    32
typedef struct {
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    33
	PyObject_HEAD
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    34
	PyObject *dict;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    35
} dirsObject;
43232
be178b5d91c8 dirs: tag a struct as not being formattable
Augie Fackler <augie@google.com>
parents: 43229
diff changeset
    36
/* clang-format on */
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    37
25093
fe3a72a3e7ca dirs.c: pass C string, not Python string, to _finddir()
Martin von Zweigbergk <martinvonz@google.com>
parents: 25092
diff changeset
    38
static inline Py_ssize_t _finddir(const char *path, Py_ssize_t pos)
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    39
{
25015
b3a68fb8b859 dirs: back out forward-searching in finddirs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 24651
diff changeset
    40
	while (pos != -1) {
25093
fe3a72a3e7ca dirs.c: pass C string, not Python string, to _finddir()
Martin von Zweigbergk <martinvonz@google.com>
parents: 25092
diff changeset
    41
		if (path[pos] == '/')
25015
b3a68fb8b859 dirs: back out forward-searching in finddirs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 24651
diff changeset
    42
			break;
b3a68fb8b859 dirs: back out forward-searching in finddirs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 24651
diff changeset
    43
		pos -= 1;
b3a68fb8b859 dirs: back out forward-searching in finddirs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 24651
diff changeset
    44
	}
42343
d8e55c0c642c util: make util.dirs() and util.finddirs() include root directory (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 34438
diff changeset
    45
	if (pos == -1) {
43233
ea62d7b06c12 dirs: give formatting oversight to clang-format
Augie Fackler <augie@google.com>
parents: 43232
diff changeset
    46
		return 0;
42343
d8e55c0c642c util: make util.dirs() and util.finddirs() include root directory (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 34438
diff changeset
    47
	}
25015
b3a68fb8b859 dirs: back out forward-searching in finddirs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 24651
diff changeset
    48
b3a68fb8b859 dirs: back out forward-searching in finddirs()
Martin von Zweigbergk <martinvonz@google.com>
parents: 24651
diff changeset
    49
	return pos;
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    50
}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    51
43658
0796e266d26b dirs: resolve fuzzer OOM situation by disallowing deep directory hierarchies
Augie Fackler <augie@google.com>
parents: 43494
diff changeset
    52
/* Mercurial will fail to run on directory hierarchies deeper than
0796e266d26b dirs: resolve fuzzer OOM situation by disallowing deep directory hierarchies
Augie Fackler <augie@google.com>
parents: 43494
diff changeset
    53
 * this constant, so we should try and keep this constant as big as
0796e266d26b dirs: resolve fuzzer OOM situation by disallowing deep directory hierarchies
Augie Fackler <augie@google.com>
parents: 43494
diff changeset
    54
 * possible.
0796e266d26b dirs: resolve fuzzer OOM situation by disallowing deep directory hierarchies
Augie Fackler <augie@google.com>
parents: 43494
diff changeset
    55
 */
0796e266d26b dirs: resolve fuzzer OOM situation by disallowing deep directory hierarchies
Augie Fackler <augie@google.com>
parents: 43494
diff changeset
    56
#define MAX_DIRS_DEPTH 2048
0796e266d26b dirs: resolve fuzzer OOM situation by disallowing deep directory hierarchies
Augie Fackler <augie@google.com>
parents: 43494
diff changeset
    57
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    58
static int _addpath(PyObject *dirs, PyObject *path)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    59
{
30105
b2f90d8878ac dirs: convert PyString to PyBytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30104
diff changeset
    60
	const char *cpath = PyBytes_AS_STRING(path);
b2f90d8878ac dirs: convert PyString to PyBytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30104
diff changeset
    61
	Py_ssize_t pos = PyBytes_GET_SIZE(path);
18901
66d3aebe2d95 dirs: use mutable integers internally
Bryan O'Sullivan <bryano@fb.com>
parents: 18900
diff changeset
    62
	PyObject *key = NULL;
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    63
	int ret = -1;
43658
0796e266d26b dirs: resolve fuzzer OOM situation by disallowing deep directory hierarchies
Augie Fackler <augie@google.com>
parents: 43494
diff changeset
    64
	size_t num_slashes = 0;
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    65
30107
da08f4707282 dirs: document performance reasons for bypassing Python C API
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30106
diff changeset
    66
	/* This loop is super critical for performance. That's why we inline
43233
ea62d7b06c12 dirs: give formatting oversight to clang-format
Augie Fackler <augie@google.com>
parents: 43232
diff changeset
    67
	 * access to Python structs instead of going through a supported API.
ea62d7b06c12 dirs: give formatting oversight to clang-format
Augie Fackler <augie@google.com>
parents: 43232
diff changeset
    68
	 * The implementation, therefore, is heavily dependent on CPython
ea62d7b06c12 dirs: give formatting oversight to clang-format
Augie Fackler <augie@google.com>
parents: 43232
diff changeset
    69
	 * implementation details. We also commit violations of the Python
ea62d7b06c12 dirs: give formatting oversight to clang-format
Augie Fackler <augie@google.com>
parents: 43232
diff changeset
    70
	 * "protocol" such as mutating immutable objects. But since we only
ea62d7b06c12 dirs: give formatting oversight to clang-format
Augie Fackler <augie@google.com>
parents: 43232
diff changeset
    71
	 * mutate objects created in this function or in other well-defined
ea62d7b06c12 dirs: give formatting oversight to clang-format
Augie Fackler <augie@google.com>
parents: 43232
diff changeset
    72
	 * locations, the references are known so these violations should go
ea62d7b06c12 dirs: give formatting oversight to clang-format
Augie Fackler <augie@google.com>
parents: 43232
diff changeset
    73
	 * unnoticed. */
25093
fe3a72a3e7ca dirs.c: pass C string, not Python string, to _finddir()
Martin von Zweigbergk <martinvonz@google.com>
parents: 25092
diff changeset
    74
	while ((pos = _finddir(cpath, pos - 1)) != -1) {
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    75
		PyObject *val;
43658
0796e266d26b dirs: resolve fuzzer OOM situation by disallowing deep directory hierarchies
Augie Fackler <augie@google.com>
parents: 43494
diff changeset
    76
		++num_slashes;
0796e266d26b dirs: resolve fuzzer OOM situation by disallowing deep directory hierarchies
Augie Fackler <augie@google.com>
parents: 43494
diff changeset
    77
		if (num_slashes > MAX_DIRS_DEPTH) {
0796e266d26b dirs: resolve fuzzer OOM situation by disallowing deep directory hierarchies
Augie Fackler <augie@google.com>
parents: 43494
diff changeset
    78
			PyErr_SetString(PyExc_ValueError,
0796e266d26b dirs: resolve fuzzer OOM situation by disallowing deep directory hierarchies
Augie Fackler <augie@google.com>
parents: 43494
diff changeset
    79
			                "Directory hierarchy too deep.");
0796e266d26b dirs: resolve fuzzer OOM situation by disallowing deep directory hierarchies
Augie Fackler <augie@google.com>
parents: 43494
diff changeset
    80
			goto bail;
0796e266d26b dirs: resolve fuzzer OOM situation by disallowing deep directory hierarchies
Augie Fackler <augie@google.com>
parents: 43494
diff changeset
    81
		}
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    82
43494
5d40317d42b7 dirs: reject consecutive slashes in paths
Augie Fackler <augie@google.com>
parents: 43233
diff changeset
    83
		/* Sniff for trailing slashes, a marker of an invalid input. */
5d40317d42b7 dirs: reject consecutive slashes in paths
Augie Fackler <augie@google.com>
parents: 43233
diff changeset
    84
		if (pos > 0 && cpath[pos - 1] == '/') {
5d40317d42b7 dirs: reject consecutive slashes in paths
Augie Fackler <augie@google.com>
parents: 43233
diff changeset
    85
			PyErr_SetString(
5d40317d42b7 dirs: reject consecutive slashes in paths
Augie Fackler <augie@google.com>
parents: 43233
diff changeset
    86
			    PyExc_ValueError,
5d40317d42b7 dirs: reject consecutive slashes in paths
Augie Fackler <augie@google.com>
parents: 43233
diff changeset
    87
			    "found invalid consecutive slashes in path");
5d40317d42b7 dirs: reject consecutive slashes in paths
Augie Fackler <augie@google.com>
parents: 43233
diff changeset
    88
			goto bail;
5d40317d42b7 dirs: reject consecutive slashes in paths
Augie Fackler <augie@google.com>
parents: 43233
diff changeset
    89
		}
5d40317d42b7 dirs: reject consecutive slashes in paths
Augie Fackler <augie@google.com>
parents: 43233
diff changeset
    90
43229
9fa941faef94 dirs: remove mutable string optimization at all
Yuya Nishihara <yuya@tcha.org>
parents: 43149
diff changeset
    91
		key = PyBytes_FromStringAndSize(cpath, pos);
9fa941faef94 dirs: remove mutable string optimization at all
Yuya Nishihara <yuya@tcha.org>
parents: 43149
diff changeset
    92
		if (key == NULL)
9fa941faef94 dirs: remove mutable string optimization at all
Yuya Nishihara <yuya@tcha.org>
parents: 43149
diff changeset
    93
			goto bail;
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    94
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
    95
		val = PyDict_GetItem(dirs, key);
18901
66d3aebe2d95 dirs: use mutable integers internally
Bryan O'Sullivan <bryano@fb.com>
parents: 18900
diff changeset
    96
		if (val != NULL) {
30106
cb3048746dae dirs: port PyInt code to work on Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30105
diff changeset
    97
			PYLONG_VALUE(val) += 1;
43229
9fa941faef94 dirs: remove mutable string optimization at all
Yuya Nishihara <yuya@tcha.org>
parents: 43149
diff changeset
    98
			Py_CLEAR(key);
25016
42e89b87ca79 dirs: speed up by storing number of direct children per dir
Martin von Zweigbergk <martinvonz@google.com>
parents: 25015
diff changeset
    99
			break;
18901
66d3aebe2d95 dirs: use mutable integers internally
Bryan O'Sullivan <bryano@fb.com>
parents: 18900
diff changeset
   100
		}
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   101
18901
66d3aebe2d95 dirs: use mutable integers internally
Bryan O'Sullivan <bryano@fb.com>
parents: 18900
diff changeset
   102
		/* Force Python to not reuse a small shared int. */
30106
cb3048746dae dirs: port PyInt code to work on Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30105
diff changeset
   103
#ifdef IS_PY3K
cb3048746dae dirs: port PyInt code to work on Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30105
diff changeset
   104
		val = PyLong_FromLong(0x1eadbeef);
cb3048746dae dirs: port PyInt code to work on Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30105
diff changeset
   105
#else
18901
66d3aebe2d95 dirs: use mutable integers internally
Bryan O'Sullivan <bryano@fb.com>
parents: 18900
diff changeset
   106
		val = PyInt_FromLong(0x1eadbeef);
30106
cb3048746dae dirs: port PyInt code to work on Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30105
diff changeset
   107
#endif
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   108
18901
66d3aebe2d95 dirs: use mutable integers internally
Bryan O'Sullivan <bryano@fb.com>
parents: 18900
diff changeset
   109
		if (val == NULL)
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   110
			goto bail;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   111
30106
cb3048746dae dirs: port PyInt code to work on Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30105
diff changeset
   112
		PYLONG_VALUE(val) = 1;
18901
66d3aebe2d95 dirs: use mutable integers internally
Bryan O'Sullivan <bryano@fb.com>
parents: 18900
diff changeset
   113
		ret = PyDict_SetItem(dirs, key, val);
66d3aebe2d95 dirs: use mutable integers internally
Bryan O'Sullivan <bryano@fb.com>
parents: 18900
diff changeset
   114
		Py_DECREF(val);
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   115
		if (ret == -1)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   116
			goto bail;
24651
67241ee427cf dirs._addpath: reinstate use of Py_CLEAR
Siddharth Agarwal <sid0@fb.com>
parents: 24624
diff changeset
   117
		Py_CLEAR(key);
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   118
	}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   119
	ret = 0;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   120
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   121
bail:
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   122
	Py_XDECREF(key);
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   123
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   124
	return ret;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   125
}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   126
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   127
static int _delpath(PyObject *dirs, PyObject *path)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   128
{
30105
b2f90d8878ac dirs: convert PyString to PyBytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30104
diff changeset
   129
	char *cpath = PyBytes_AS_STRING(path);
b2f90d8878ac dirs: convert PyString to PyBytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30104
diff changeset
   130
	Py_ssize_t pos = PyBytes_GET_SIZE(path);
18901
66d3aebe2d95 dirs: use mutable integers internally
Bryan O'Sullivan <bryano@fb.com>
parents: 18900
diff changeset
   131
	PyObject *key = NULL;
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   132
	int ret = -1;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   133
25093
fe3a72a3e7ca dirs.c: pass C string, not Python string, to _finddir()
Martin von Zweigbergk <martinvonz@google.com>
parents: 25092
diff changeset
   134
	while ((pos = _finddir(cpath, pos - 1)) != -1) {
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   135
		PyObject *val;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   136
30105
b2f90d8878ac dirs: convert PyString to PyBytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30104
diff changeset
   137
		key = PyBytes_FromStringAndSize(cpath, pos);
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   138
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   139
		if (key == NULL)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   140
			goto bail;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   141
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   142
		val = PyDict_GetItem(dirs, key);
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   143
		if (val == NULL) {
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   144
			PyErr_SetString(PyExc_ValueError,
43233
ea62d7b06c12 dirs: give formatting oversight to clang-format
Augie Fackler <augie@google.com>
parents: 43232
diff changeset
   145
			                "expected a value, found none");
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   146
			goto bail;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   147
		}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   148
30106
cb3048746dae dirs: port PyInt code to work on Python 3
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30105
diff changeset
   149
		if (--PYLONG_VALUE(val) <= 0) {
25016
42e89b87ca79 dirs: speed up by storing number of direct children per dir
Martin von Zweigbergk <martinvonz@google.com>
parents: 25015
diff changeset
   150
			if (PyDict_DelItem(dirs, key) == -1)
42e89b87ca79 dirs: speed up by storing number of direct children per dir
Martin von Zweigbergk <martinvonz@google.com>
parents: 25015
diff changeset
   151
				goto bail;
42e89b87ca79 dirs: speed up by storing number of direct children per dir
Martin von Zweigbergk <martinvonz@google.com>
parents: 25015
diff changeset
   152
		} else
42e89b87ca79 dirs: speed up by storing number of direct children per dir
Martin von Zweigbergk <martinvonz@google.com>
parents: 25015
diff changeset
   153
			break;
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   154
		Py_CLEAR(key);
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   155
	}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   156
	ret = 0;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   157
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   158
bail:
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   159
	Py_XDECREF(key);
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   160
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   161
	return ret;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   162
}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   163
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   164
static int dirs_fromdict(PyObject *dirs, PyObject *source, char skipchar)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   165
{
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   166
	PyObject *key, *value;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   167
	Py_ssize_t pos = 0;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   168
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   169
	while (PyDict_Next(source, &pos, &key, &value)) {
30105
b2f90d8878ac dirs: convert PyString to PyBytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30104
diff changeset
   170
		if (!PyBytes_Check(key)) {
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   171
			PyErr_SetString(PyExc_TypeError, "expected string key");
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   172
			return -1;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   173
		}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   174
		if (skipchar) {
21809
e250b8300e6e parsers: inline fields of dirstate values in C version
Siddharth Agarwal <sid0@fb.com>
parents: 18902
diff changeset
   175
			if (!dirstate_tuple_check(value)) {
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   176
				PyErr_SetString(PyExc_TypeError,
43233
ea62d7b06c12 dirs: give formatting oversight to clang-format
Augie Fackler <augie@google.com>
parents: 43232
diff changeset
   177
				                "expected a dirstate tuple");
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   178
				return -1;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   179
			}
21809
e250b8300e6e parsers: inline fields of dirstate values in C version
Siddharth Agarwal <sid0@fb.com>
parents: 18902
diff changeset
   180
			if (((dirstateTupleObject *)value)->state == skipchar)
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   181
				continue;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   182
		}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   183
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   184
		if (_addpath(dirs, key) == -1)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   185
			return -1;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   186
	}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   187
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   188
	return 0;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   189
}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   190
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   191
static int dirs_fromiter(PyObject *dirs, PyObject *source)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   192
{
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   193
	PyObject *iter, *item = NULL;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   194
	int ret;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   195
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   196
	iter = PyObject_GetIter(source);
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   197
	if (iter == NULL)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   198
		return -1;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   199
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   200
	while ((item = PyIter_Next(iter)) != NULL) {
30105
b2f90d8878ac dirs: convert PyString to PyBytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30104
diff changeset
   201
		if (!PyBytes_Check(item)) {
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   202
			PyErr_SetString(PyExc_TypeError, "expected string");
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   203
			break;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   204
		}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   205
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   206
		if (_addpath(dirs, item) == -1)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   207
			break;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   208
		Py_CLEAR(item);
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   209
	}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   210
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   211
	ret = PyErr_Occurred() ? -1 : 0;
23960
bca4b6f126f2 dirs: fix leak of iterator in dirs_fromiter
Augie Fackler <augie@google.com>
parents: 21809
diff changeset
   212
	Py_DECREF(iter);
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   213
	Py_XDECREF(item);
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   214
	return ret;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   215
}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   216
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   217
/*
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   218
 * Calculate a refcounted set of directory names for the files in a
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   219
 * dirstate.
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   220
 */
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   221
static int dirs_init(dirsObject *self, PyObject *args)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   222
{
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   223
	PyObject *dirs = NULL, *source = NULL;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   224
	char skipchar = 0;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   225
	int ret = -1;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   226
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   227
	self->dict = NULL;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   228
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   229
	if (!PyArg_ParseTuple(args, "|Oc:__init__", &source, &skipchar))
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   230
		return -1;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   231
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   232
	dirs = PyDict_New();
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   233
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   234
	if (dirs == NULL)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   235
		return -1;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   236
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   237
	if (source == NULL)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   238
		ret = 0;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   239
	else if (PyDict_Check(source))
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   240
		ret = dirs_fromdict(dirs, source, skipchar);
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   241
	else if (skipchar)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   242
		PyErr_SetString(PyExc_ValueError,
43233
ea62d7b06c12 dirs: give formatting oversight to clang-format
Augie Fackler <augie@google.com>
parents: 43232
diff changeset
   243
		                "skip character is only supported "
ea62d7b06c12 dirs: give formatting oversight to clang-format
Augie Fackler <augie@google.com>
parents: 43232
diff changeset
   244
		                "with a dict source");
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   245
	else
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   246
		ret = dirs_fromiter(dirs, source);
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   247
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   248
	if (ret == -1)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   249
		Py_XDECREF(dirs);
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   250
	else
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   251
		self->dict = dirs;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   252
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   253
	return ret;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   254
}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   255
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   256
PyObject *dirs_addpath(dirsObject *self, PyObject *args)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   257
{
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   258
	PyObject *path;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   259
30105
b2f90d8878ac dirs: convert PyString to PyBytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30104
diff changeset
   260
	if (!PyArg_ParseTuple(args, "O!:addpath", &PyBytes_Type, &path))
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   261
		return NULL;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   262
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   263
	if (_addpath(self->dict, path) == -1)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   264
		return NULL;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   265
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   266
	Py_RETURN_NONE;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   267
}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   268
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   269
static PyObject *dirs_delpath(dirsObject *self, PyObject *args)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   270
{
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   271
	PyObject *path;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   272
30105
b2f90d8878ac dirs: convert PyString to PyBytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30104
diff changeset
   273
	if (!PyArg_ParseTuple(args, "O!:delpath", &PyBytes_Type, &path))
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   274
		return NULL;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   275
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   276
	if (_delpath(self->dict, path) == -1)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   277
		return NULL;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   278
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   279
	Py_RETURN_NONE;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   280
}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   281
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   282
static int dirs_contains(dirsObject *self, PyObject *value)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   283
{
30105
b2f90d8878ac dirs: convert PyString to PyBytes
Gregory Szorc <gregory.szorc@gmail.com>
parents: 30104
diff changeset
   284
	return PyBytes_Check(value) ? PyDict_Contains(self->dict, value) : 0;
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   285
}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   286
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   287
static void dirs_dealloc(dirsObject *self)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   288
{
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   289
	Py_XDECREF(self->dict);
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   290
	PyObject_Del(self);
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   291
}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   292
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   293
static PyObject *dirs_iter(dirsObject *self)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   294
{
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   295
	return PyObject_GetIter(self->dict);
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   296
}
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   297
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   298
static PySequenceMethods dirs_sequence_methods;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   299
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   300
static PyMethodDef dirs_methods[] = {
43233
ea62d7b06c12 dirs: give formatting oversight to clang-format
Augie Fackler <augie@google.com>
parents: 43232
diff changeset
   301
    {"addpath", (PyCFunction)dirs_addpath, METH_VARARGS, "add a path"},
ea62d7b06c12 dirs: give formatting oversight to clang-format
Augie Fackler <augie@google.com>
parents: 43232
diff changeset
   302
    {"delpath", (PyCFunction)dirs_delpath, METH_VARARGS, "remove a path"},
ea62d7b06c12 dirs: give formatting oversight to clang-format
Augie Fackler <augie@google.com>
parents: 43232
diff changeset
   303
    {NULL} /* Sentinel */
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   304
};
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   305
43233
ea62d7b06c12 dirs: give formatting oversight to clang-format
Augie Fackler <augie@google.com>
parents: 43232
diff changeset
   306
static PyTypeObject dirsType = {PyVarObject_HEAD_INIT(NULL, 0)};
18900
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   307
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   308
void dirs_module_init(PyObject *mod)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   309
{
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   310
	dirs_sequence_methods.sq_contains = (objobjproc)dirs_contains;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   311
	dirsType.tp_name = "parsers.dirs";
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   312
	dirsType.tp_new = PyType_GenericNew;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   313
	dirsType.tp_basicsize = sizeof(dirsObject);
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   314
	dirsType.tp_dealloc = (destructor)dirs_dealloc;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   315
	dirsType.tp_as_sequence = &dirs_sequence_methods;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   316
	dirsType.tp_flags = Py_TPFLAGS_DEFAULT;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   317
	dirsType.tp_doc = "dirs";
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   318
	dirsType.tp_iter = (getiterfunc)dirs_iter;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   319
	dirsType.tp_methods = dirs_methods;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   320
	dirsType.tp_init = (initproc)dirs_init;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   321
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   322
	if (PyType_Ready(&dirsType) < 0)
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   323
		return;
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   324
	Py_INCREF(&dirsType);
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   325
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   326
	PyModule_AddObject(mod, "dirs", (PyObject *)&dirsType);
02ee846b246a scmutil: rewrite dirs in C, use if available
Bryan O'Sullivan <bryano@fb.com>
parents:
diff changeset
   327
}