Re: [PATCH 1 of 5] rust-cpython: put leaked reference in PyLeakedRef
On Sun, Oct 13, 2019 at 8:52 PM Yuya Nishihara wrote: > On Sun, 13 Oct 2019 07:46:14 -0700, Martin von Zweigbergk wrote: > > On Sat, Oct 12, 2019, 01:06 Yuya Nishihara wrote: > > > # HG changeset patch > > > # User Yuya Nishihara > > > # Date 1568552779 -32400 > > > # Sun Sep 15 22:06:19 2019 +0900 > > > # Node ID 458c6598a13caee640294d88af4e93783fc36476 > > > # Parent ce20b870041fc4d6ba6989acbb9373797ce9b3d6 > > > rust-cpython: put leaked reference in PyLeakedRef > > > > -/// Returns a leaked reference and its management object. > > > +/// Returns a leaked reference. > > > /// > > > /// # Safety > > > /// > > > /// It's up to you to make sure that the management object lives > > > /// longer than the leaked reference. Otherwise, you'll get a > > > /// dangling reference. > > > > > > > This seems inaccurate, or at least unclear, now. > > Yeah, it could be rephrased as "Returns a leaked reference temporarily > held by its management object." I don't care much about the document > accuracy of intermediate patches. > Sorry, I had not realized the comment was changed in a later patch. > > > > @@ -318,12 +319,13 @@ macro_rules! py_shared_ref { > > > /// > > > /// In truth, this does not represent leaked references themselves; > > > /// it is instead useful alongside them to manage them. > > > > So does this. > > This one is still true in this patch. PyLeakedRef doesn't provide any > smart-pointer-like functions yet. > Oh, I guess I misunderstood what this comment was about. I had thought that storing the reference in the management object (as we do after this patch) would count as "represent". I'll queue this mostly based on Georges' review, thanks. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 8] eol: test-eol-update.t coverage around update --clean using filters ... badly
On Mon, 14 Oct 2019 02:13:35 +0200, Mads Kiilerich wrote: > # HG changeset patch > # User Mads Kiilerich > # Date 1571004565 -7200 > # Mon Oct 14 00:09:25 2019 +0200 > # Node ID 57f88532f7005eeb13cb06418ae3a3b156085adf > # Parent 52781d57313d512efb7150603104bea3ca11d0eb > eol: test-eol-update.t coverage around update --clean using filters ... badly Queued the series, thanks. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 2 of 8] localrepo: debug log of filter name when filtering through a function
On Mon, 14 Oct 2019 02:13:36 +0200, Mads Kiilerich wrote: > # HG changeset patch > # User Mads Kiilerich > # Date 1570970400 -7200 > # Sun Oct 13 14:40:00 2019 +0200 > # Node ID 2b91375a812ce3c694efa35a98a109387962 > # Parent 57f88532f7005eeb13cb06418ae3a3b156085adf > localrepo: debug log of filter name when filtering through a function > @@ -1907,7 +1909,8 @@ class localrepository(object): > def _filter(self, filterpats, filename, data): > for mf, fn, cmd in filterpats: > if mf(filename): > -self.ui.debug(b"filtering %s through %s\n" % (filename, cmd)) > +self.ui.debug(b"filtering %s through %s\n" % > + (filename, cmd or > pycompat.bytestr(fn.__name__))) Nit: changed pycompat.bytestr() to pycompat.sysbytes() in flight. Function names should be ascii in general, but that isn't guaranteed. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 2] patchcopies: give up any optimization based on `introrev`
On Sun, 13 Oct 2019 23:02:25 +0200, Pierre-Yves David wrote: > On 10/13/19 12:08 PM, Yuya Nishihara wrote: > > On Fri, 11 Oct 2019 20:00:58 +0200, Pierre-Yves David wrote: > >> On 10/11/19 2:02 PM, Yuya Nishihara wrote: > >>> On Fri, 11 Oct 2019 01:04:12 +0200, Pierre-Yves David wrote: > # HG changeset patch > # User Pierre-Yves David > # Date 1570672173 -7200 > # Thu Oct 10 03:49:33 2019 +0200 > # Node ID 2477ba483c04067900d1e9f6523b03df68a4d545 > # Parent 8ff1ecfadcd110849c47c77e31c92809eea466ab > # EXP-Topic patchcopies-regression > # Available At https://bitbucket.org/octobus/mercurial-devel/ > # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r > 2477ba483c04 > patchcopies: give up any optimization based on `introrev` > > Between 8a0136f69027 and d98fb3f42f33, we sped up the search for the > introduction revision during path copies. However, further checking show > that > finding the introduction revision is still expensive and that we are > better off > without it. So we simply drop it and only rely on the linkrev > optimisation. > > I ran `perfpathcopies` on 6989 pair of revision in the pypy > repository (`hg perfhelper-pathcopies`. The result is massively in favor > of > dropping this condition. The result of the copy tracing are unchanged. > > Attempt to use a smaller changes preserving linkrev usage were > unsuccessful, it > can return wrong result. The following changesets broke > test-mv-cp-st-diff.t > > -if not f.isintroducedafter(limit): > +if limit >= 0 and f.linkrev() < limit: > return None > >>> > >>> Sure. I meant comparing linkrevs, not linkrev vs (changelog) rev. If both > >>> arms were linkrevs, and if the limit pointed to the revision where the > >>> linkrevs of its files are guaranteed to be the lowest, the comparison > >>> (e.g. f.linkrev() < repo[limit][path].linkrev()) would work. > >>> > >>> My question was whether it would make things fast or not. > >> > >> Ha, I understand your proposal better now. > >> > >> My testing of the version in this patch versus the "wrong" version using > >> linkrev too agressively did not show a significant difference (-1%). > > > > Do you mean only 1% speedup or measurable speedup on 1% cases? I don't think > > the former is significant, but the latter could be depending on use cases. > > only ±1% speedup for all (many) cases I looked at. > > >> So > >> I don't it to raise anything better. Can we move forward with this > >> series and maybe try a different approach later ? > > > > Better to leave the _findlimit() function? Or won't it be any useful in > > your future work? > > That seems easy enough t reintroduce later if needed. My current > optimization work focus on the changeset based copies tracing algorithm. > I don't think I'll spend much time on the filelog based one. Fair enough. Queued the series, thanks. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH V2] dirs: remove mutable string optimization at all
# HG changeset patch # User Yuya Nishihara # Date 1570964769 -32400 # Sun Oct 13 20:06:09 2019 +0900 # Node ID dd9f93e8af83be1bfd7082026d28f774917f0593 # Parent feaea7fe888383bcb1d28e69df325e41ef68ece9 dirs: remove mutable string optimization at all As far as I can see, the optimization trick has been dead since 42e89b87ca79 "dirs: speed up by storing number of direct children per dir". After 42e89b87ca79, the key variable is cleared to NULL at each iteration. diff --git a/mercurial/cext/dirs.c b/mercurial/cext/dirs.c --- a/mercurial/cext/dirs.c +++ b/mercurial/cext/dirs.c @@ -26,9 +26,6 @@ * * We modify Python integers for refcounting, but those integers are * never visible to Python code. - * - * We mutate strings in-place, but leave them immutable once they can - * be seen by Python code. */ typedef struct { PyObject_HEAD @@ -63,46 +60,18 @@ static int _addpath(PyObject *dirs, PyOb * "protocol" such as mutating immutable objects. But since we only * mutate objects created in this function or in other well-defined * locations, the references are known so these violations should go - * unnoticed. The code for adjusting the length of a PyBytesObject is - * essentially a minimal version of _PyBytes_Resize. */ + * unnoticed. */ while ((pos = _finddir(cpath, pos - 1)) != -1) { PyObject *val; - if (pos < 2) { - key = PyBytes_FromStringAndSize(cpath, pos); - if (key == NULL) - goto bail; - } else { - /* It's likely that every prefix already has an entry - in our dict. Try to avoid allocating and - deallocating a string for each prefix we check. */ - if (key != NULL) - ((PyBytesObject *)key)->ob_shash = -1; - else { - /* We know pos >= 2, so we won't get a small -* shared string. */ - key = PyBytes_FromStringAndSize(cpath, pos); - if (key == NULL) - goto bail; - } - /* Py_SIZE(o) refers to the ob_size member of -* the struct. Yes, assigning to what looks -* like a function seems wrong. */ - Py_SIZE(key) = pos; - ((PyBytesObject *)key)->ob_sval[pos] = '\0'; - } + key = PyBytes_FromStringAndSize(cpath, pos); + if (key == NULL) + goto bail; val = PyDict_GetItem(dirs, key); if (val != NULL) { PYLONG_VALUE(val) += 1; - if (pos < 2) { - /* This was a short string, so we -* probably got a small shared string -* we can't mutate on the next loop -* iteration. Clear it. -*/ - Py_CLEAR(key); - } + Py_CLEAR(key); break; } ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 5] rust-cpython: put leaked reference in PyLeakedRef
On Sun, 13 Oct 2019 07:46:14 -0700, Martin von Zweigbergk wrote: > On Sat, Oct 12, 2019, 01:06 Yuya Nishihara wrote: > > # HG changeset patch > > # User Yuya Nishihara > > # Date 1568552779 -32400 > > # Sun Sep 15 22:06:19 2019 +0900 > > # Node ID 458c6598a13caee640294d88af4e93783fc36476 > > # Parent ce20b870041fc4d6ba6989acbb9373797ce9b3d6 > > rust-cpython: put leaked reference in PyLeakedRef > > -/// Returns a leaked reference and its management object. > > +/// Returns a leaked reference. > > /// > > /// # Safety > > /// > > /// It's up to you to make sure that the management object lives > > /// longer than the leaked reference. Otherwise, you'll get a > > /// dangling reference. > > > > This seems inaccurate, or at least unclear, now. Yeah, it could be rephrased as "Returns a leaked reference temporarily held by its management object." I don't care much about the document accuracy of intermediate patches. > > @@ -318,12 +319,13 @@ macro_rules! py_shared_ref { > > /// > > /// In truth, this does not represent leaked references themselves; > > /// it is instead useful alongside them to manage them. > > So does this. This one is still true in this patch. PyLeakedRef doesn't provide any smart-pointer-like functions yet. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH] dirs: remove mutable string optimization at all
On Sun, 13 Oct 2019 15:33:28 -0400, Matt Harbison wrote: > On Sun, 13 Oct 2019 07:27:32 -0400, Yuya Nishihara wrote: > > > # HG changeset patch > > # User Yuya Nishihara > > # Date 1570964769 -32400 > > # Sun Oct 13 20:06:09 2019 +0900 > > # Node ID 87dfcdb8394e377049b5a337585309ae4c652c7d > > # Parent ce20b870041fc4d6ba6989acbb9373797ce9b3d6 > > dirs: remove mutable string optimization at all > > Should this original comment go away too? > > https://www.mercurial-scm.org/repo/hg/file/52781d57313d/mercurial/cext/dirs.c#l30 Good catch. I'll send V2. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 8 of 8] eol: don't fallback to use .hgeol from tip (BC)
# HG changeset patch # User Mads Kiilerich # Date 1570925426 -7200 # Sun Oct 13 02:10:26 2019 +0200 # Node ID 74c8ac8124723f06a612ff560403d4bd288ec5f4 # Parent 68dde01bb05c782d484d96e424512b89e0673bec eol: don't fallback to use .hgeol from tip (BC) If no .hgeol were found in the current working directory, eol would fallback to use the one in tip. That could in some cases give very confusing or wrong behaviour when it applied wrong filters. It might be convenient to have plain 'clone' immediately apply 'native' encoding patterns in the cloned repo. But it is wrong to assume that this revision is tip, and even more wrong to also apply it when not cloning - for example when updating between history revisions. The encoding should always match the content of the current .hgeol . It should never use anything else. diff --git a/hgext/eol.py b/hgext/eol.py --- a/hgext/eol.py +++ b/hgext/eol.py @@ -387,7 +387,7 @@ def reposetup(ui, repo): return eol.match def _hgcleardirstate(self): -self._eolmatch = self.loadeol([None, b'tip']) +self._eolmatch = self.loadeol([None]) if not self._eolmatch: self._eolmatch = util.never return diff --git a/tests/test-eol-clone.t b/tests/test-eol-clone.t --- a/tests/test-eol-clone.t +++ b/tests/test-eol-clone.t @@ -21,9 +21,8 @@ setup repository adding .hgeol adding a.txt -Test commit of removed .hgeol - currently it seems to live on as zombie -(causing "filtering a.txt through tolf") after being removed ... but actually -it is just confusing use of tip revision. +Test commit of removed .hgeol and how it immediately makes the automatic +changes explicit and committable. $ cd .. $ hg clone repo repo-2 @@ -41,7 +40,7 @@ it is just confusing use of tip revision $ hg remove .hgeol $ touch a.txt * # ensure consistent st dirtyness checks, ignoring dirstate timing $ hg st -v --debug - filtering a.txt through tolf + M a.txt R .hgeol $ hg commit -m 'remove eol' $ hg exp @@ -49,16 +48,26 @@ it is just confusing use of tip revision # User test # Date 0 0 # Thu Jan 01 00:00:00 1970 + - # Node ID c60b96c20c7de8c821127b548c34e5b170bcf9fe + # Node ID 3c20c2d90333b6ecdc8f7aa8f9b73223c7c7a608 # Parent 90f94e2cf4e24628afddd641688dfe4cd476d6e4 remove eol - diff -r 90f94e2cf4e2 -r c60b96c20c7d .hgeol + diff -r 90f94e2cf4e2 -r 3c20c2d90333 .hgeol --- a/.hgeol Thu Jan 01 00:00:00 1970 + +++ /dev/nullThu Jan 01 00:00:00 1970 + @@ -1,2 +0,0 @@ -[patterns] -**.txt = native + diff -r 90f94e2cf4e2 -r 3c20c2d90333 a.txt + --- a/a.txt Thu Jan 01 00:00:00 1970 + + +++ b/a.txt Thu Jan 01 00:00:00 1970 + + @@ -1,3 +1,3 @@ + -first + -second + -third + +first\r (esc) + +second\r (esc) + +third\r (esc) $ hg push --quiet $ cd .. @@ -75,7 +84,7 @@ the source repo: updating to branch default resolving manifests branchmerge: False, force: False, partial: False - ancestor: , local: +, remote: c60b96c20c7d + ancestor: , local: +, remote: 3c20c2d90333 calling hook preupdate.eol: hgext.eol.preupdate a.txt: remote created -> g getting a.txt @@ -83,9 +92,9 @@ the source repo: $ cd repo-3 $ cat a.txt - first - second - third + first\r (esc) + second\r (esc) + third\r (esc) Test clone of revision with .hgeol ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 7 of 8] eol: tweak test-eol-clone.t with better descriptions and logging
# HG changeset patch # User Mads Kiilerich # Date 1571010144 -7200 # Mon Oct 14 01:42:24 2019 +0200 # Node ID 68dde01bb05c782d484d96e424512b89e0673bec # Parent 950c89a71e9837dc81da80ed34eee9b602a808d9 eol: tweak test-eol-clone.t with better descriptions and logging Expose impact of changes coming next ... diff --git a/tests/test-eol-clone.t b/tests/test-eol-clone.t --- a/tests/test-eol-clone.t +++ b/tests/test-eol-clone.t @@ -21,7 +21,9 @@ setup repository adding .hgeol adding a.txt -Clone +Test commit of removed .hgeol - currently it seems to live on as zombie +(causing "filtering a.txt through tolf") after being removed ... but actually +it is just confusing use of tip revision. $ cd .. $ hg clone repo repo-2 @@ -37,14 +39,46 @@ Clone second third $ hg remove .hgeol + $ touch a.txt * # ensure consistent st dirtyness checks, ignoring dirstate timing + $ hg st -v --debug + filtering a.txt through tolf + R .hgeol $ hg commit -m 'remove eol' + $ hg exp + # HG changeset patch + # User test + # Date 0 0 + # Thu Jan 01 00:00:00 1970 + + # Node ID c60b96c20c7de8c821127b548c34e5b170bcf9fe + # Parent 90f94e2cf4e24628afddd641688dfe4cd476d6e4 + remove eol + + diff -r 90f94e2cf4e2 -r c60b96c20c7d .hgeol + --- a/.hgeol Thu Jan 01 00:00:00 1970 + + +++ /dev/nullThu Jan 01 00:00:00 1970 + + @@ -1,2 +0,0 @@ + -[patterns] + -**.txt = native $ hg push --quiet $ cd .. -Test clone of repo with .hgeol in working dir, but no .hgeol in tip +Test clone of repo with .hgeol in working dir, but no .hgeol in default +checkout revision tip. The repo is correctly updated to be consistent and have +the exact content checked out without filtering, ignoring the current .hgeol in +the source repo: - $ hg clone repo repo-3 + $ cat repo/.hgeol + [patterns] + **.txt = native + $ hg clone repo repo-3 -v --debug + linked 7 files updating to branch default + resolving manifests + branchmerge: False, force: False, partial: False + ancestor: , local: +, remote: c60b96c20c7d + calling hook preupdate.eol: hgext.eol.preupdate + a.txt: remote created -> g + getting a.txt 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd repo-3 ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 6 of 8] eol: fix update - don't use and apply removed .hgeol patterns
# HG changeset patch # User Mads Kiilerich # Date 1570925707 -7200 # Sun Oct 13 02:15:07 2019 +0200 # Node ID 950c89a71e9837dc81da80ed34eee9b602a808d9 # Parent 844fa54a1ffbc052fbcd76f103b3db6b02a84690 eol: fix update - don't use and apply removed .hgeol patterns 'hg up -C' to revisions with different .hgeol patterns could leave dirty changes in the working directory. That could make deployment of new .hgeol filters tricky: they would "occasionally" apply also in branches where they shouldn't. Fixed by dropping all old patterns before applying new ones. diff --git a/hgext/eol.py b/hgext/eol.py --- a/hgext/eol.py +++ b/hgext/eol.py @@ -221,6 +221,12 @@ class eolfile(object): self.match = match.match(root, b'', [], include, exclude) def copytoui(self, ui): +newpatterns = set(pattern for pattern, key, m in self.patterns) +for section in (b'decode', b'encode'): +for oldpattern, _filter in ui.configitems(section): +if oldpattern not in newpatterns: +if ui.configsource(section, oldpattern) == b'eol': +ui.setconfig(section, oldpattern, b'!', b'eol') for pattern, key, m in self.patterns: try: ui.setconfig(b'decode', pattern, self._decode[key], b'eol') diff --git a/tests/test-eol-update.t b/tests/test-eol-update.t --- a/tests/test-eol-update.t +++ b/tests/test-eol-update.t @@ -120,12 +120,6 @@ Test EOL update first -second third - diff --git a/f b/f - --- a/f - +++ b/f - @@ -1,1 +1,1 @@ - -f\r (esc) - +f $ dotest CRLF % hg clone repo repo-CRLF @@ -159,12 +153,6 @@ Test EOL update first -second third - diff --git a/f b/f - --- a/f - +++ b/f - @@ -1,1 +1,1 @@ - -f\r (esc) - +f Test in repo using eol extension, while keeping an eye on how filters are applied: @@ -177,8 +165,8 @@ applied: > eol = > EOF -Update to revision 0 which has no .hgeol . Unfortunately, it uses the filter -from tip ... which evidently is wrong: +Update to revision 0 which has no .hgeol, shouldn't use any filters, and +obviously should leave things as tidy as they were before the clean update. $ hg up -c -r 0 -v --debug resolving manifests @@ -193,22 +181,8 @@ from tip ... which evidently is wrong: filtering a.txt through tolf f: remote created -> g getting f - filtering f through tolf 3 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg st - M f - $ touch .hgeol * # ensure consistent dirtyness checks ignoring dirstate - $ hg up -C -r 0 -v --debug - eol: detected change in .hgeol - filtering .hgeol through isbinary - filtering a.txt through tolf - resolving manifests - branchmerge: False, force: True, partial: False - ancestor: 15cbdf8ca3db+, local: 15cbdf8ca3db+, remote: 15cbdf8ca3db - calling hook preupdate.eol: hgext.eol.preupdate - f: remote is newer -> g - getting f - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg branch b marked working directory as branch b @@ -250,9 +224,9 @@ Merge changes that apply a filter to f: -f\r (esc) +f -Abort the merge with up -C to revision 0 ... but notice how .hgeol changes are -not detected correctly: f is filtered with tolf even though there is no filter -for f in revision 0, and it thus ends up with working directory changes. +Abort the merge with up -C to revision 0. +Note that files are filtered correctly for revision 0: f is not filtered, a.txt +is filtered with tolf, and everything is left tidy. $ touch .hgeol * # ensure consistent dirtyness checks ignoring dirstate $ hg up -C -r 0 -v --debug @@ -269,7 +243,6 @@ for f in revision 0, and it thus ends up filtering a.txt through tolf f: remote is newer -> g getting f - filtering f through tolf 3 files updated, 0 files merged, 0 files removed, 0 files unresolved $ touch .hgeol * @@ -277,16 +250,9 @@ for f in revision 0, and it thus ends up eol: detected change in .hgeol filtering .hgeol through isbinary filtering a.txt through tolf - M f $ hg diff - diff --git a/f b/f - --- a/f - +++ b/f - @@ -1,1 +1,1 @@ - -f\r (esc) - +f -Workaround: Update again - this will read the right .hgeol: +Things were clean, and updating again will not change anything: $ touch .hgeol * $ hg up -C -r 0 -v --debug @@ -297,9 +263,7 @@ Workaround: Update again - this will rea branchmerge: False, force: True, partial: False ancestor: 15cbdf8ca3db+, local: 15cbdf8ca3db+, remote: 15cbdf8ca3db calling hook preupdate.eol: hgext.eol.preupdate - f: remote is newer -> g - getting f - 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved $ touch .hgeol * $ hg st --debug ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org
[PATCH 4 of 8] eol: update isbinary filter to work without compat wrapper
# HG changeset patch # User Mads Kiilerich # Date 1571009598 -7200 # Mon Oct 14 01:33:18 2019 +0200 # Node ID 5670699747c92d725927e25754817d5aa498d728 # Parent 1e663f4a658dbf6669c9bfd53918bf1daa734dc6 eol: update isbinary filter to work without compat wrapper diff --git a/hgext/eol.py b/hgext/eol.py --- a/hgext/eol.py +++ b/hgext/eol.py @@ -165,7 +165,7 @@ def tocrlf(s, params, ui, **kwargs): return util.tocrlf(s) -def isbinary(s, params): +def isbinary(s, params, ui, **kwargs): """Filter to do nothing with the file.""" return s diff --git a/tests/test-eol-update.t b/tests/test-eol-update.t --- a/tests/test-eol-update.t +++ b/tests/test-eol-update.t @@ -187,7 +187,7 @@ from tip ... which evidently is wrong: calling hook preupdate.eol: hgext.eol.preupdate .hgeol: remote created -> g getting .hgeol - filtering .hgeol through compat-isbinary + filtering .hgeol through isbinary a.txt: remote created -> g getting a.txt filtering a.txt through tolf @@ -200,7 +200,7 @@ from tip ... which evidently is wrong: $ touch .hgeol * # ensure consistent dirtyness checks ignoring dirstate $ hg up -C -r 0 -v --debug eol: detected change in .hgeol - filtering .hgeol through compat-isbinary + filtering .hgeol through isbinary filtering a.txt through tolf resolving manifests branchmerge: False, force: True, partial: False @@ -263,7 +263,7 @@ for f in revision 0, and it thus ends up calling hook preupdate.eol: hgext.eol.preupdate .hgeol: remote is newer -> g getting .hgeol - filtering .hgeol through compat-isbinary + filtering .hgeol through isbinary a.txt: remote is newer -> g getting a.txt filtering a.txt through tolf @@ -275,7 +275,7 @@ for f in revision 0, and it thus ends up $ touch .hgeol * $ hg st --debug eol: detected change in .hgeol - filtering .hgeol through compat-isbinary + filtering .hgeol through isbinary filtering a.txt through tolf M f $ hg diff @@ -291,7 +291,7 @@ Workaround: Update again - this will rea $ touch .hgeol * $ hg up -C -r 0 -v --debug eol: detected change in .hgeol - filtering .hgeol through compat-isbinary + filtering .hgeol through isbinary filtering a.txt through tolf resolving manifests branchmerge: False, force: True, partial: False @@ -304,7 +304,7 @@ Workaround: Update again - this will rea $ touch .hgeol * $ hg st --debug eol: detected change in .hgeol - filtering .hgeol through compat-isbinary + filtering .hgeol through isbinary filtering a.txt through tolf $ cd .. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 3 of 8] localrepo: fix variable binding in handling of old filters
# HG changeset patch # User Mads Kiilerich # Date 1570925119 -7200 # Sun Oct 13 02:05:19 2019 +0200 # Node ID 1e663f4a658dbf6669c9bfd53918bf1daa734dc6 # Parent 2b91375a812ce3c694efa35a98a109387962 localrepo: fix variable binding in handling of old filters The lambda was referencing oldfn in outer scope without binding the current value. If oldfn function were reassigned before use, wrong filters could be used. Fixed by having oldfn as named parameter default value of the lambda. diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -1900,7 +1900,7 @@ class localrepository(object): # Wrap old filters not supporting keyword arguments if not pycompat.getargspec(fn)[2]: oldfn = fn -fn = lambda s, c, **kwargs: oldfn(s, c) +fn = lambda s, c, oldfn=oldfn, **kwargs: oldfn(s, c) fn.__name__ = 'compat-' + oldfn.__name__ l.append((mf, fn, params)) self._filterpats[filter] = l ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 5 of 8] eol: cache needs update, also if it has same timestamp as the source
# HG changeset patch # User Mads Kiilerich # Date 1570925493 -7200 # Sun Oct 13 02:11:33 2019 +0200 # Node ID 844fa54a1ffbc052fbcd76f103b3db6b02a84690 # Parent 5670699747c92d725927e25754817d5aa498d728 eol: cache needs update, also if it has same timestamp as the source Ignoring same timestamp could (in theory?) cause changes to not be detected. It might happen quite often that the cache is populated right after .hgeol has been updated and they thus have the same time stamp second. But we want correctness, and if it populates the cache so fast, then it can also not be a big problem to run it again next time when the timestamp has moved on. diff --git a/hgext/eol.py b/hgext/eol.py --- a/hgext/eol.py +++ b/hgext/eol.py @@ -401,7 +401,7 @@ def reposetup(ui, repo): except OSError: eolmtime = 0 -if eolmtime > cachemtime: +if eolmtime >= cachemtime and eolmtime > 0: self.ui.debug(b"eol: detected change in .hgeol\n") hgeoldata = self.wvfs.read(b'.hgeol') ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 8] localrepo: debug log of filter name when filtering through a function
# HG changeset patch # User Mads Kiilerich # Date 1570970400 -7200 # Sun Oct 13 14:40:00 2019 +0200 # Node ID 2b91375a812ce3c694efa35a98a109387962 # Parent 57f88532f7005eeb13cb06418ae3a3b156085adf localrepo: debug log of filter name when filtering through a function diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py --- a/mercurial/localrepo.py +++ b/mercurial/localrepo.py @@ -1896,10 +1896,12 @@ class localrepository(object): break if not fn: fn = lambda s, c, **kwargs: procutil.filter(s, c) +fn.__name__ = 'commandfilter' # Wrap old filters not supporting keyword arguments if not pycompat.getargspec(fn)[2]: oldfn = fn fn = lambda s, c, **kwargs: oldfn(s, c) +fn.__name__ = 'compat-' + oldfn.__name__ l.append((mf, fn, params)) self._filterpats[filter] = l return self._filterpats[filter] @@ -1907,7 +1909,8 @@ class localrepository(object): def _filter(self, filterpats, filename, data): for mf, fn, cmd in filterpats: if mf(filename): -self.ui.debug(b"filtering %s through %s\n" % (filename, cmd)) +self.ui.debug(b"filtering %s through %s\n" % + (filename, cmd or pycompat.bytestr(fn.__name__))) data = fn(data, cmd, ui=self.ui, repo=self, filename=filename) break diff --git a/tests/test-eol-update.t b/tests/test-eol-update.t --- a/tests/test-eol-update.t +++ b/tests/test-eol-update.t @@ -187,21 +187,21 @@ from tip ... which evidently is wrong: calling hook preupdate.eol: hgext.eol.preupdate .hgeol: remote created -> g getting .hgeol - filtering .hgeol through + filtering .hgeol through compat-isbinary a.txt: remote created -> g getting a.txt - filtering a.txt through + filtering a.txt through tolf f: remote created -> g getting f - filtering f through + filtering f through tolf 3 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg st M f $ touch .hgeol * # ensure consistent dirtyness checks ignoring dirstate $ hg up -C -r 0 -v --debug eol: detected change in .hgeol - filtering .hgeol through - filtering a.txt through + filtering .hgeol through compat-isbinary + filtering a.txt through tolf resolving manifests branchmerge: False, force: True, partial: False ancestor: 15cbdf8ca3db+, local: 15cbdf8ca3db+, remote: 15cbdf8ca3db @@ -263,20 +263,20 @@ for f in revision 0, and it thus ends up calling hook preupdate.eol: hgext.eol.preupdate .hgeol: remote is newer -> g getting .hgeol - filtering .hgeol through + filtering .hgeol through compat-isbinary a.txt: remote is newer -> g getting a.txt - filtering a.txt through + filtering a.txt through tolf f: remote is newer -> g getting f - filtering f through + filtering f through tolf 3 files updated, 0 files merged, 0 files removed, 0 files unresolved $ touch .hgeol * $ hg st --debug eol: detected change in .hgeol - filtering .hgeol through - filtering a.txt through + filtering .hgeol through compat-isbinary + filtering a.txt through tolf M f $ hg diff diff --git a/f b/f @@ -291,8 +291,8 @@ Workaround: Update again - this will rea $ touch .hgeol * $ hg up -C -r 0 -v --debug eol: detected change in .hgeol - filtering .hgeol through - filtering a.txt through + filtering .hgeol through compat-isbinary + filtering a.txt through tolf resolving manifests branchmerge: False, force: True, partial: False ancestor: 15cbdf8ca3db+, local: 15cbdf8ca3db+, remote: 15cbdf8ca3db @@ -304,8 +304,8 @@ Workaround: Update again - this will rea $ touch .hgeol * $ hg st --debug eol: detected change in .hgeol - filtering .hgeol through - filtering a.txt through + filtering .hgeol through compat-isbinary + filtering a.txt through tolf $ cd .. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 8] eol: test-eol-update.t coverage around update --clean using filters ... badly
# HG changeset patch # User Mads Kiilerich # Date 1571004565 -7200 # Mon Oct 14 00:09:25 2019 +0200 # Node ID 57f88532f7005eeb13cb06418ae3a3b156085adf # Parent 52781d57313d512efb7150603104bea3ca11d0eb eol: test-eol-update.t coverage around update --clean using filters ... badly This will reveal problems and track their fixes. diff --git a/tests/test-eol-update.t b/tests/test-eol-update.t --- a/tests/test-eol-update.t +++ b/tests/test-eol-update.t @@ -26,14 +26,17 @@ Test EOL update > EOF > > printf "first\nsecond\nthird\n" > a.txt + > printf "f\r\n" > f > hg commit --addremove -m 'LF commit' > > cat > .hgeol < [patterns] > **.txt = CRLF + > f = LF > EOF > > printf "first\r\nsecond\r\nthird\r\n" > a.txt + > printf "f\n" > f > hg commit -m 'CRLF commit' > > cd .. @@ -83,10 +86,11 @@ Test EOL update % hg init adding .hgeol adding a.txt + adding f $ dotest LF % hg clone repo repo-LF - 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved % a.txt (before) first\r (esc) second\r (esc) @@ -104,7 +108,7 @@ Test EOL update third\r (esc) % hg update 0 merging a.txt - 1 files updated, 1 files merged, 0 files removed, 0 files unresolved + 2 files updated, 1 files merged, 0 files removed, 0 files unresolved % a.txt first third @@ -116,10 +120,16 @@ Test EOL update first -second third + diff --git a/f b/f + --- a/f + +++ b/f + @@ -1,1 +1,1 @@ + -f\r (esc) + +f $ dotest CRLF % hg clone repo repo-CRLF - 2 files updated, 0 files merged, 0 files removed, 0 files unresolved + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved % a.txt (before) first\r (esc) second\r (esc) @@ -137,7 +147,7 @@ Test EOL update third\r (esc) % hg update 0 merging a.txt - 1 files updated, 1 files merged, 0 files removed, 0 files unresolved + 2 files updated, 1 files merged, 0 files removed, 0 files unresolved % a.txt first third @@ -149,4 +159,154 @@ Test EOL update first -second third + diff --git a/f b/f + --- a/f + +++ b/f + @@ -1,1 +1,1 @@ + -f\r (esc) + +f + +Test in repo using eol extension, while keeping an eye on how filters are +applied: + + $ cd repo + + $ hg up -q -c -r null + $ cat > .hg/hgrc < [extensions] + > eol = + > EOF + +Update to revision 0 which has no .hgeol . Unfortunately, it uses the filter +from tip ... which evidently is wrong: + + $ hg up -c -r 0 -v --debug + resolving manifests + branchmerge: False, force: False, partial: False + ancestor: , local: +, remote: 15cbdf8ca3db + calling hook preupdate.eol: hgext.eol.preupdate + .hgeol: remote created -> g + getting .hgeol + filtering .hgeol through + a.txt: remote created -> g + getting a.txt + filtering a.txt through + f: remote created -> g + getting f + filtering f through + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ hg st + M f + $ touch .hgeol * # ensure consistent dirtyness checks ignoring dirstate + $ hg up -C -r 0 -v --debug + eol: detected change in .hgeol + filtering .hgeol through + filtering a.txt through + resolving manifests + branchmerge: False, force: True, partial: False + ancestor: 15cbdf8ca3db+, local: 15cbdf8ca3db+, remote: 15cbdf8ca3db + calling hook preupdate.eol: hgext.eol.preupdate + f: remote is newer -> g + getting f + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + + $ hg branch b + marked working directory as branch b + (branches are permanent and global, did you want a bookmark?) + $ hg ci -m b + +Merge changes that apply a filter to f: + + $ hg merge 1 + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + $ hg st + M .hgeol + M a.txt + M f + $ hg diff + diff --git a/.hgeol b/.hgeol + --- a/.hgeol + +++ b/.hgeol + @@ -1,2 +1,3 @@ + [patterns] + -**.txt = LF + +**.txt = CRLF + +f = LF + diff --git a/a.txt b/a.txt + --- a/a.txt + +++ b/a.txt + @@ -1,3 +1,3 @@ + -first + -second + -third + +first\r (esc) + +second\r (esc) + +third\r (esc) + diff --git a/f b/f + --- a/f + +++ b/f + @@ -1,1 +1,1 @@ + -f\r (esc) + +f + +Abort the merge with up -C to revision 0 ... but notice how .hgeol changes are +not detected correctly: f is filtered with tolf even though there is no filter +for f in revision 0, and it thus ends up with working directory changes. + + $ touch .hgeol * # ensure consistent dirtyness checks ignoring dirstate + $ hg up -C -r 0 -v --debug + eol: detected change in .hgeol + resolving manifests + branchmerge: False, force: True, partial: False + ancestor: 1db78bdd3bd6+, local: 1db78bdd3bd6+, remote: 15cbdf8ca3db + calling hook preupdate.eol: hgext.eol.preupdate + .hgeol: remote is newer -> g +
Re: [PATCH 1 of 2] patchcopies: give up any optimization based on `introrev`
On 10/13/19 12:08 PM, Yuya Nishihara wrote: On Fri, 11 Oct 2019 20:00:58 +0200, Pierre-Yves David wrote: On 10/11/19 2:02 PM, Yuya Nishihara wrote: On Fri, 11 Oct 2019 01:04:12 +0200, Pierre-Yves David wrote: # HG changeset patch # User Pierre-Yves David # Date 1570672173 -7200 # Thu Oct 10 03:49:33 2019 +0200 # Node ID 2477ba483c04067900d1e9f6523b03df68a4d545 # Parent 8ff1ecfadcd110849c47c77e31c92809eea466ab # EXP-Topic patchcopies-regression # Available At https://bitbucket.org/octobus/mercurial-devel/ # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 2477ba483c04 patchcopies: give up any optimization based on `introrev` Between 8a0136f69027 and d98fb3f42f33, we sped up the search for the introduction revision during path copies. However, further checking show that finding the introduction revision is still expensive and that we are better off without it. So we simply drop it and only rely on the linkrev optimisation. I ran `perfpathcopies` on 6989 pair of revision in the pypy repository (`hg perfhelper-pathcopies`. The result is massively in favor of dropping this condition. The result of the copy tracing are unchanged. Attempt to use a smaller changes preserving linkrev usage were unsuccessful, it can return wrong result. The following changesets broke test-mv-cp-st-diff.t -if not f.isintroducedafter(limit): +if limit >= 0 and f.linkrev() < limit: return None Sure. I meant comparing linkrevs, not linkrev vs (changelog) rev. If both arms were linkrevs, and if the limit pointed to the revision where the linkrevs of its files are guaranteed to be the lowest, the comparison (e.g. f.linkrev() < repo[limit][path].linkrev()) would work. My question was whether it would make things fast or not. Ha, I understand your proposal better now. My testing of the version in this patch versus the "wrong" version using linkrev too agressively did not show a significant difference (-1%). Do you mean only 1% speedup or measurable speedup on 1% cases? I don't think the former is significant, but the latter could be depending on use cases. only ±1% speedup for all (many) cases I looked at. So I don't it to raise anything better. Can we move forward with this series and maybe try a different approach later ? Better to leave the _findlimit() function? Or won't it be any useful in your future work? That seems easy enough t reintroduce later if needed. My current optimization work focus on the changeset based copies tracing algorithm. I don't think I'll spend much time on the filelog based one. -- Pierre-Yves David ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 5] rust-cpython: put leaked reference in PyLeakedRef
On Sat, Oct 12, 2019, 01:06 Yuya Nishihara wrote: > # HG changeset patch > # User Yuya Nishihara > # Date 1568552779 -32400 > # Sun Sep 15 22:06:19 2019 +0900 > # Node ID 458c6598a13caee640294d88af4e93783fc36476 > # Parent ce20b870041fc4d6ba6989acbb9373797ce9b3d6 > rust-cpython: put leaked reference in PyLeakedRef > > The next patch will make PyLeakedRef manage the lifetime of the underlying > object. leak_handle.data.take() will be removed soon. > > diff --git a/rust/hg-cpython/src/dirstate/copymap.rs > b/rust/hg-cpython/src/dirstate/copymap.rs > --- a/rust/hg-cpython/src/dirstate/copymap.rs > +++ b/rust/hg-cpython/src/dirstate/copymap.rs > @@ -13,6 +13,7 @@ use std::cell::RefCell; > > use crate::dirstate::dirstate_map::DirstateMap; > use crate::ref_sharing::PyLeakedRef; > +use hg::DirstateMap as RustDirstateMap; > use hg::{utils::hg_path::HgPathBuf, CopyMapIter}; > > py_class!(pub class CopyMap |py| { > @@ -104,7 +105,7 @@ impl CopyMap { > > py_shared_iterator!( > CopyMapKeysIterator, > -PyLeakedRef, > +PyLeakedRef<&'static RustDirstateMap>, > CopyMapIter<'static>, > CopyMap::translate_key, > Option > @@ -112,7 +113,7 @@ py_shared_iterator!( > > py_shared_iterator!( > CopyMapItemsIterator, > -PyLeakedRef, > +PyLeakedRef<&'static RustDirstateMap>, > CopyMapIter<'static>, > CopyMap::translate_key_value, > Option<(PyBytes, PyBytes)> > diff --git a/rust/hg-cpython/src/dirstate/dirs_multiset.rs > b/rust/hg-cpython/src/dirstate/dirs_multiset.rs > --- a/rust/hg-cpython/src/dirstate/dirs_multiset.rs > +++ b/rust/hg-cpython/src/dirstate/dirs_multiset.rs > @@ -92,8 +92,9 @@ py_class!(pub class Dirs |py| { > }) > } > def __iter__() -> PyResult { > -let (leak_handle, leaked_ref) = > +let mut leak_handle = > unsafe { self.inner_shared(py).leak_immutable()? }; > +let leaked_ref = leak_handle.data.take().unwrap(); > DirsMultisetKeysIterator::from_inner( > py, > leak_handle, > @@ -125,7 +126,7 @@ impl Dirs { > > py_shared_iterator!( > DirsMultisetKeysIterator, > -PyLeakedRef, > +PyLeakedRef<&'static DirsMultiset>, > DirsMultisetIter<'static>, > Dirs::translate_key, > Option > diff --git a/rust/hg-cpython/src/dirstate/dirstate_map.rs > b/rust/hg-cpython/src/dirstate/dirstate_map.rs > --- a/rust/hg-cpython/src/dirstate/dirstate_map.rs > +++ b/rust/hg-cpython/src/dirstate/dirstate_map.rs > @@ -321,8 +321,9 @@ py_class!(pub class DirstateMap |py| { > } > > def keys() -> PyResult { > -let (leak_handle, leaked_ref) = > +let mut leak_handle = > unsafe { self.inner_shared(py).leak_immutable()? }; > +let leaked_ref = leak_handle.data.take().unwrap(); > DirstateMapKeysIterator::from_inner( > py, > leak_handle, > @@ -331,8 +332,9 @@ py_class!(pub class DirstateMap |py| { > } > > def items() -> PyResult { > -let (leak_handle, leaked_ref) = > +let mut leak_handle = > unsafe { self.inner_shared(py).leak_immutable()? }; > +let leaked_ref = leak_handle.data.take().unwrap(); > DirstateMapItemsIterator::from_inner( > py, > leak_handle, > @@ -341,8 +343,9 @@ py_class!(pub class DirstateMap |py| { > } > > def __iter__() -> PyResult { > -let (leak_handle, leaked_ref) = > +let mut leak_handle = > unsafe { self.inner_shared(py).leak_immutable()? }; > +let leaked_ref = leak_handle.data.take().unwrap(); > DirstateMapKeysIterator::from_inner( > py, > leak_handle, > @@ -460,8 +463,9 @@ py_class!(pub class DirstateMap |py| { > } > > def copymapiter() -> PyResult { > -let (leak_handle, leaked_ref) = > +let mut leak_handle = > unsafe { self.inner_shared(py).leak_immutable()? }; > +let leaked_ref = leak_handle.data.take().unwrap(); > CopyMapKeysIterator::from_inner( > py, > leak_handle, > @@ -470,8 +474,9 @@ py_class!(pub class DirstateMap |py| { > } > > def copymapitemsiter() -> PyResult { > -let (leak_handle, leaked_ref) = > +let mut leak_handle = > unsafe { self.inner_shared(py).leak_immutable()? }; > +let leaked_ref = leak_handle.data.take().unwrap(); > CopyMapItemsIterator::from_inner( > py, > leak_handle, > @@ -513,7 +518,7 @@ py_shared_ref!(DirstateMap, RustDirstate > > py_shared_iterator!( > DirstateMapKeysIterator, > -PyLeakedRef, > +PyLeakedRef<&'static RustDirstateMap>, > StateMapIter<'static>, > DirstateMap::translate_key, > Option > @@ -521,7 +526,7 @@ py_shared_iterator!( > > py_shared_iterator!( > DirstateMapItemsIterator, > -PyLeakedRef, > +PyLeakedRef<&'static RustDirstateMap>, >
Re: [PATCH 1 of 7] rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
On Sun, 13 Oct 2019 22:41:37 +0900, Yuya Nishihara wrote: > # HG changeset patch > # User Yuya Nishihara > # Date 1570953317 -32400 > # Sun Oct 13 16:55:17 2019 +0900 > # Node ID 083f70b7b5899755bb28ce16d6fc45eee46e84e4 > # Parent dbe969ca04b9711aa3b244b2dcea9b9925bab960 > rust-cpython: add wrapper around decapsule_make_dirstate_tuple() This is actually V2. I forgot to add --flag V2, sorry. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 7 of 7] rust-cpython: drop direct dependency on python(27|3)_sys
# HG changeset patch # User Yuya Nishihara # Date 1570970825 -32400 # Sun Oct 13 21:47:05 2019 +0900 # Node ID f04203256726d2172b0aa42311263f56dd12d3ac # Parent 7ac435844d990e027d8b589909ca42d17a89b6b4 rust-cpython: drop direct dependency on python(27|3)_sys We no longer use it. diff --git a/rust/Cargo.lock b/rust/Cargo.lock --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -66,8 +66,6 @@ dependencies = [ "cpython 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hg-core 0.1.0", "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "python27-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "python3-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/rust/hg-cpython/Cargo.toml b/rust/hg-cpython/Cargo.toml --- a/rust/hg-cpython/Cargo.toml +++ b/rust/hg-cpython/Cargo.toml @@ -11,12 +11,9 @@ crate-type = ["cdylib"] [features] default = ["python27"] -python27 = ["cpython/python27-sys", -"cpython/extension-module-2-7", -"python27-sys", -] +python27 = ["cpython/python27-sys", "cpython/extension-module-2-7"] -python3 = ["python3-sys", "cpython/python3-sys", "cpython/extension-module"] +python3 = ["cpython/python3-sys", "cpython/extension-module"] [dependencies] hg-core = { path = "../hg-core" } @@ -25,11 +22,3 @@ libc = '*' [dependencies.cpython] version = "0.3" default-features = false - -[dependencies.python27-sys] -version = "0.3" -optional = true - -[dependencies.python3-sys] -version = "0.3" -optional = true ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 6 of 7] rust-cpython: leverage upstreamed py_capsule_fn!() macro
# HG changeset patch # User Yuya Nishihara # Date 1570954064 -32400 # Sun Oct 13 17:07:44 2019 +0900 # Node ID 7ac435844d990e027d8b589909ca42d17a89b6b4 # Parent 7073183d7ec824b6b3686b41b6c0a98d089a6447 rust-cpython: leverage upstreamed py_capsule_fn!() macro diff --git a/rust/hg-cpython/src/cindex.rs b/rust/hg-cpython/src/cindex.rs --- a/rust/hg-cpython/src/cindex.rs +++ b/rust/hg-cpython/src/cindex.rs @@ -9,23 +9,20 @@ //! //! Ideally, we should use an Index entirely implemented in Rust, //! but this will take some time to get there. -#[cfg(feature = "python27")] -use python27_sys as python_sys; -#[cfg(feature = "python3")] -use python3_sys as python_sys; -use cpython::{PyClone, PyErr, PyObject, PyResult, Python}; +use cpython::{PyClone, PyObject, PyResult, Python}; use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION}; use libc::c_int; -use python_sys::PyCapsule_Import; -use std::ffi::CStr; -use std::mem::transmute; -type IndexParentsFn = unsafe extern "C" fn( -index: *mut python_sys::PyObject, -rev: c_int, -ps: *mut [c_int; 2], -) -> c_int; +py_capsule_fn!( +from mercurial.cext.parsers import index_get_parents_CAPI +as get_parents_capi +signature ( +index: *mut RawPyObject, +rev: c_int, +ps: *mut [c_int; 2], +) -> c_int +); /// A `Graph` backed up by objects and functions from revlog.c /// @@ -61,14 +58,14 @@ type IndexParentsFn = unsafe extern "C" /// mechanisms in other contexts. pub struct Index { index: PyObject, -parents: IndexParentsFn, +parents: get_parents_capi::CapsuleFn, } impl Index { pub fn new(py: Python, index: PyObject) -> PyResult { Ok(Index { index: index, -parents: decapsule_parents_fn(py)?, +parents: get_parents_capi::retrieve(py)?, }) } } @@ -103,31 +100,3 @@ impl Graph for Index { } } } - -/// Return the `index_get_parents` function of the parsers C Extension module. -/// -/// A pointer to the function is stored in the `parsers` module as a -/// standard [Python capsule](https://docs.python.org/2/c-api/capsule.html). -/// -/// This function retrieves the capsule and casts the function pointer -/// -/// Casting function pointers is one of the rare cases of -/// legitimate use cases of `mem::transmute()` (see -/// https://doc.rust-lang.org/std/mem/fn.transmute.html of -/// `mem::transmute()`. -/// It is inappropriate for architectures where -/// function and data pointer sizes differ (so-called "Harvard -/// architectures"), but these are nowadays mostly DSPs -/// and microcontrollers, hence out of our scope. -fn decapsule_parents_fn(py: Python) -> PyResult { -unsafe { -let caps_name = CStr::from_bytes_with_nul_unchecked( -b"mercurial.cext.parsers.index_get_parents_CAPI\0", -); -let from_caps = PyCapsule_Import(caps_name.as_ptr(), 0); -if from_caps.is_null() { -return Err(PyErr::fetch(py)); -} -Ok(transmute(from_caps)) -} -} diff --git a/rust/hg-cpython/src/dirstate.rs b/rust/hg-cpython/src/dirstate.rs --- a/rust/hg-cpython/src/dirstate.rs +++ b/rust/hg-cpython/src/dirstate.rs @@ -22,14 +22,7 @@ use hg::{ StateMap, }; use libc::{c_char, c_int}; -#[cfg(feature = "python27")] -use python27_sys as python_sys; -#[cfg(feature = "python3")] -use python3_sys as python_sys; -use python_sys::PyCapsule_Import; use std::convert::TryFrom; -use std::ffi::CStr; -use std::mem::transmute; // C code uses a custom `dirstate_tuple` type, checks in multiple instances // for this type, and raises a Python `Exception` if the check does not pass. @@ -37,34 +30,23 @@ use std::mem::transmute; // would be a good idea in the near future to remove it entirely to allow // for a pure Python tuple of the same effective structure to be used, // rendering this type and the capsule below useless. -type MakeDirstateTupleFn = unsafe extern "C" fn( -state: c_char, -mode: c_int, -size: c_int, -mtime: c_int, -) -> *mut python_sys::PyObject; - -// This is largely a copy/paste from cindex.rs, pending the merge of a -// `py_capsule_fn!` macro in the rust-cpython project: -// https://github.com/dgrunwald/rust-cpython/pull/169 -fn decapsule_make_dirstate_tuple(py: Python) -> PyResult { -unsafe { -let caps_name = CStr::from_bytes_with_nul_unchecked( -b"mercurial.cext.parsers.make_dirstate_tuple_CAPI\0", -); -let from_caps = PyCapsule_Import(caps_name.as_ptr(), 0); -if from_caps.is_null() { -return Err(PyErr::fetch(py)); -} -Ok(transmute(from_caps)) -} -} +py_capsule_fn!( +from mercurial.cext.parsers import make_dirstate_tuple_CAPI +as make_dirstate_tuple_capi +signature ( +state: c_char, +mode: c_int, +size: c_int, +mtime: c_int, +) -> *mut RawPyObject +);
[PATCH 5 of 7] rust-cpython: bump cpython crates to 0.3
# HG changeset patch # User Yuya Nishihara # Date 1570953909 -32400 # Sun Oct 13 17:05:09 2019 +0900 # Node ID 7073183d7ec824b6b3686b41b6c0a98d089a6447 # Parent d7823e47559d0b0aec701c9f6cc8f66ae59ecaa1 rust-cpython: bump cpython crates to 0.3 Unblocks py_capsule_fn!(). diff --git a/rust/Cargo.lock b/rust/Cargo.lock --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -33,13 +33,13 @@ dependencies = [ [[package]] name = "cpython" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index; dependencies = [ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "python27-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "python27-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "python3-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -63,11 +63,11 @@ dependencies = [ name = "hg-cpython" version = "0.1.0" dependencies = [ - "cpython 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cpython 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hg-core 0.1.0", "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "python27-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "python27-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "python3-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -100,7 +100,7 @@ source = "registry+https://github.com/ru [[package]] name = "python27-sys" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index; dependencies = [ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", @@ -109,7 +109,7 @@ dependencies = [ [[package]] name = "python3-sys" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index; dependencies = [ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", @@ -304,14 +304,14 @@ source = "registry+https://github.com/ru "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum cpython 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b489034e723e7f5109fecd19b719e664f89ef925be785885252469e9822fa940" +"checksum cpython 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85532c648315aeb0829ad216a6a29aa3212cf9319bc7f6daf1404aa0bdd1485f" "checksum fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81f7f8eb465745ea9b02e2704612a9946a59fa40572086c6fd49d6ddcf30bf31" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum python27-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "56114c37d4dca82526d74009df7782a28c871ac9d36b19d4cb9e67672258527e" -"checksum python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "61e4aac43f833fd637e429506cb2ac9d7df672c4b68f2eaaa163649b7fdc0444" +"checksum python27-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "372555e88a6bc8109eb641380240dc8d25a128fc48363ec9075664daadffdd5b" +"checksum python3-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3a8ebed3f1201fda179f3960609dbbc10cd8c75e9f2afcb03788278f367d8ea" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a6321f5f8c7411e5be7eed4b" diff --git
[PATCH 4 of 7] rust-cpython: turn inline comments into non-doc comments
# HG changeset patch # User Yuya Nishihara # Date 1570953746 -32400 # Sun Oct 13 17:02:26 2019 +0900 # Node ID d7823e47559d0b0aec701c9f6cc8f66ae59ecaa1 # Parent 1c18f9652cda28e7d8d0ffc2e7a01d16622bc98f rust-cpython: turn inline comments into non-doc comments diff --git a/rust/hg-cpython/src/dirstate.rs b/rust/hg-cpython/src/dirstate.rs --- a/rust/hg-cpython/src/dirstate.rs +++ b/rust/hg-cpython/src/dirstate.rs @@ -31,12 +31,12 @@ use std::convert::TryFrom; use std::ffi::CStr; use std::mem::transmute; -/// C code uses a custom `dirstate_tuple` type, checks in multiple instances -/// for this type, and raises a Python `Exception` if the check does not pass. -/// Because this type differs only in name from the regular Python tuple, it -/// would be a good idea in the near future to remove it entirely to allow -/// for a pure Python tuple of the same effective structure to be used, -/// rendering this type and the capsule below useless. +// C code uses a custom `dirstate_tuple` type, checks in multiple instances +// for this type, and raises a Python `Exception` if the check does not pass. +// Because this type differs only in name from the regular Python tuple, it +// would be a good idea in the near future to remove it entirely to allow +// for a pure Python tuple of the same effective structure to be used, +// rendering this type and the capsule below useless. type MakeDirstateTupleFn = unsafe extern "C" fn( state: c_char, mode: c_int, @@ -44,9 +44,9 @@ type MakeDirstateTupleFn = unsafe extern mtime: c_int, ) -> *mut python_sys::PyObject; -/// This is largely a copy/paste from cindex.rs, pending the merge of a -/// `py_capsule_fn!` macro in the rust-cpython project: -/// https://github.com/dgrunwald/rust-cpython/pull/169 +// This is largely a copy/paste from cindex.rs, pending the merge of a +// `py_capsule_fn!` macro in the rust-cpython project: +// https://github.com/dgrunwald/rust-cpython/pull/169 fn decapsule_make_dirstate_tuple(py: Python) -> PyResult { unsafe { let caps_name = CStr::from_bytes_with_nul_unchecked( ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 3 of 7] rust-cpython: fix signature of make_dirstate_tuple()
# HG changeset patch # User Yuya Nishihara # Date 1570953670 -32400 # Sun Oct 13 17:01:10 2019 +0900 # Node ID 1c18f9652cda28e7d8d0ffc2e7a01d16622bc98f # Parent 46a5d47e23a43c12115de6707fe727e52a8a5f74 rust-cpython: fix signature of make_dirstate_tuple() Fortunately, the layout of PyObject {} is compatible with a C pointer, but we shouldn't rely on that. This also fixes the handling of NULL pointer. diff --git a/rust/hg-cpython/src/dirstate.rs b/rust/hg-cpython/src/dirstate.rs --- a/rust/hg-cpython/src/dirstate.rs +++ b/rust/hg-cpython/src/dirstate.rs @@ -23,9 +23,10 @@ use hg::{ }; use libc::{c_char, c_int}; #[cfg(feature = "python27")] -use python27_sys::PyCapsule_Import; +use python27_sys as python_sys; #[cfg(feature = "python3")] -use python3_sys::PyCapsule_Import; +use python3_sys as python_sys; +use python_sys::PyCapsule_Import; use std::convert::TryFrom; use std::ffi::CStr; use std::mem::transmute; @@ -41,7 +42,7 @@ type MakeDirstateTupleFn = unsafe extern mode: c_int, size: c_int, mtime: c_int, -) -> PyObject; +) -> *mut python_sys::PyObject; /// This is largely a copy/paste from cindex.rs, pending the merge of a /// `py_capsule_fn!` macro in the rust-cpython project: @@ -76,10 +77,11 @@ pub fn make_dirstate_tuple( // just do a naive enum cast. let state_code: u8 = state.into(); -unsafe { +let maybe_obj = unsafe { let ptr = make(state_code as c_char, mode, size, mtime); -Ok(ptr) -} +PyObject::from_owned_ptr_opt(py, ptr) +}; +maybe_obj.ok_or_else(|| PyErr::fetch(py)) } pub fn extract_dirstate(py: Python, dmap: ) -> Result { ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 7] rust-cpython: mark capsule function as unsafe
# HG changeset patch # User Yuya Nishihara # Date 1570953495 -32400 # Sun Oct 13 16:58:15 2019 +0900 # Node ID 46a5d47e23a43c12115de6707fe727e52a8a5f74 # Parent 083f70b7b5899755bb28ce16d6fc45eee46e84e4 rust-cpython: mark capsule function as unsafe diff --git a/rust/hg-cpython/src/dirstate.rs b/rust/hg-cpython/src/dirstate.rs --- a/rust/hg-cpython/src/dirstate.rs +++ b/rust/hg-cpython/src/dirstate.rs @@ -36,7 +36,7 @@ use std::mem::transmute; /// would be a good idea in the near future to remove it entirely to allow /// for a pure Python tuple of the same effective structure to be used, /// rendering this type and the capsule below useless. -type MakeDirstateTupleFn = extern "C" fn( +type MakeDirstateTupleFn = unsafe extern "C" fn( state: c_char, mode: c_int, size: c_int, @@ -75,7 +75,11 @@ pub fn make_dirstate_tuple( // because Into has a specific implementation while `as c_char` would // just do a naive enum cast. let state_code: u8 = state.into(); -Ok(make(state_code as c_char, mode, size, mtime)) + +unsafe { +let ptr = make(state_code as c_char, mode, size, mtime); +Ok(ptr) +} } pub fn extract_dirstate(py: Python, dmap: ) -> Result { ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 1 of 7] rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
# HG changeset patch # User Yuya Nishihara # Date 1570953317 -32400 # Sun Oct 13 16:55:17 2019 +0900 # Node ID 083f70b7b5899755bb28ce16d6fc45eee46e84e4 # Parent dbe969ca04b9711aa3b244b2dcea9b9925bab960 rust-cpython: add wrapper around decapsule_make_dirstate_tuple() There are a couple of safety issues. First, the returned function pointer must be unsafe. Second, its return value must be a raw pointer (i.e. python27_sys::PyObject), not a cpython::PyObject. The wrapper function will address these issues. diff --git a/rust/hg-cpython/src/dirstate.rs b/rust/hg-cpython/src/dirstate.rs --- a/rust/hg-cpython/src/dirstate.rs +++ b/rust/hg-cpython/src/dirstate.rs @@ -46,9 +46,7 @@ type MakeDirstateTupleFn = extern "C" fn /// This is largely a copy/paste from cindex.rs, pending the merge of a /// `py_capsule_fn!` macro in the rust-cpython project: /// https://github.com/dgrunwald/rust-cpython/pull/169 -pub fn decapsule_make_dirstate_tuple( -py: Python, -) -> PyResult { +fn decapsule_make_dirstate_tuple(py: Python) -> PyResult { unsafe { let caps_name = CStr::from_bytes_with_nul_unchecked( b"mercurial.cext.parsers.make_dirstate_tuple_CAPI\0", @@ -61,6 +59,25 @@ pub fn decapsule_make_dirstate_tuple( } } +pub fn make_dirstate_tuple( +py: Python, +entry: , +) -> PyResult { +let make = decapsule_make_dirstate_tuple(py)?; + +let { +state, +mode, +size, +mtime, +} = entry; +// Explicitly go through u8 first, then cast to platform-specific `c_char` +// because Into has a specific implementation while `as c_char` would +// just do a naive enum cast. +let state_code: u8 = state.into(); +Ok(make(state_code as c_char, mode, size, mtime)) +} + pub fn extract_dirstate(py: Python, dmap: ) -> Result { dmap.items(py) .iter() diff --git a/rust/hg-cpython/src/dirstate/dirstate_map.rs b/rust/hg-cpython/src/dirstate/dirstate_map.rs --- a/rust/hg-cpython/src/dirstate/dirstate_map.rs +++ b/rust/hg-cpython/src/dirstate/dirstate_map.rs @@ -16,11 +16,10 @@ use cpython::{ exc, ObjectProtocol, PyBool, PyBytes, PyClone, PyDict, PyErr, PyObject, PyResult, PyTuple, Python, PythonObject, ToPyObject, }; -use libc::c_char; use crate::{ dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator}, -dirstate::{decapsule_make_dirstate_tuple, dirs_multiset::Dirs}, +dirstate::{dirs_multiset::Dirs, make_dirstate_tuple}, ref_sharing::{PyLeakedRef, PySharedRefCell}, }; use hg::{ @@ -66,15 +65,7 @@ py_class!(pub class DirstateMap |py| { let key = key.extract::(py)?; match self.inner_shared(py).borrow().get(HgPath::new(key.data(py))) { Some(entry) => { -// Explicitly go through u8 first, then cast to -// platform-specific `c_char`. -let state: u8 = entry.state.into(); -Ok(Some(decapsule_make_dirstate_tuple(py)?( -state as c_char, -entry.mode, -entry.size, -entry.mtime, -))) +Ok(Some(make_dirstate_tuple(py, entry)?)) }, None => Ok(default) } @@ -303,15 +294,7 @@ py_class!(pub class DirstateMap |py| { let key = HgPath::new(key.data(py)); match self.inner_shared(py).borrow().get(key) { Some(entry) => { -// Explicitly go through u8 first, then cast to -// platform-specific `c_char`. -let state: u8 = entry.state.into(); -Ok(decapsule_make_dirstate_tuple(py)?( -state as c_char, -entry.mode, -entry.size, -entry.mtime, -)) +Ok(make_dirstate_tuple(py, entry)?) }, None => Err(PyErr::new::( py, @@ -483,18 +466,9 @@ impl DirstateMap { res: (, ), ) -> PyResult> { let (f, entry) = res; - -// Explicitly go through u8 first, then cast to -// platform-specific `c_char`. -let state: u8 = entry.state.into(); Ok(Some(( PyBytes::new(py, f.as_ref()), -decapsule_make_dirstate_tuple(py)?( -state as c_char, -entry.mode, -entry.size, -entry.mtime, -), +make_dirstate_tuple(py, entry)?, ))) } } diff --git a/rust/hg-cpython/src/parsers.rs b/rust/hg-cpython/src/parsers.rs --- a/rust/hg-cpython/src/parsers.rs +++ b/rust/hg-cpython/src/parsers.rs @@ -15,15 +15,13 @@ use cpython::{ PythonObject, ToPyObject, }; use hg::{ -pack_dirstate, parse_dirstate, utils::hg_path::HgPathBuf, DirstateEntry, +pack_dirstate, parse_dirstate, utils::hg_path::HgPathBuf, DirstatePackError, DirstateParents,
Re: [PATCH 7 of 7] rust-cpython: leverage upstreamed py_capsule_fn!() macro
On 10/13/19 2:37 PM, Yuya Nishihara wrote: > On Sun, 13 Oct 2019 14:08:24 +0200, Georges Racinet wrote: >>> +py_capsule_fn!( >>> +from mercurial.cext.parsers import index_get_parents_CAPI >>> +as get_parents_capi >>> +signature ( >>> +index: *mut python_sys::PyObject, >> Here you can directly use RawPyObject: >> >> index: *mut RawPyObject, >> >> see >> https://github.com/dgrunwald/rust-cpython/commit/c5cfd32cf05005e3ad515063c9ca14100362eb93 > Oh, there is. I was looking for cpython::RawPyObject and failed. That's actually how my first attempt looked like IIRC, but Mark preferred it to be enclosed in the capsule submodule to limit that abstraction leak to cases where it's really needed. > > I'll send V2 shortly. Cool, once it's landed, I'll send the remainders of my own series: removal of `py_set()` in favour of `cpython::objects::PySet`. Regards, -- Georges Racinet https://octobus.net GPG: BF5456F4DC625443849B6E58EE20CA44EF691D39, sur serveurs publics signature.asc Description: OpenPGP digital signature ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 7 of 7] rust-cpython: leverage upstreamed py_capsule_fn!() macro
On Sun, 13 Oct 2019 14:08:24 +0200, Georges Racinet wrote: > > +py_capsule_fn!( > > +from mercurial.cext.parsers import index_get_parents_CAPI > > +as get_parents_capi > > +signature ( > > +index: *mut python_sys::PyObject, > > Here you can directly use RawPyObject: > > index: *mut RawPyObject, > > see > https://github.com/dgrunwald/rust-cpython/commit/c5cfd32cf05005e3ad515063c9ca14100362eb93 Oh, there is. I was looking for cpython::RawPyObject and failed. I'll send V2 shortly. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 7 of 7] rust-cpython: leverage upstreamed py_capsule_fn!() macro
Hi, I don't have time for a formal review right now, but I did skim over the series, and I think it can be simplified and pushed further, removing the whole sys_python dependency (see the inline comment below) Actually I have a series of my own in the works to the same effect, i.e., leveraging the rust-cpython 0.3.0 and its more integrated) capsule integration. Here it is for reference: https://dev.heptapod.net/octobus/mercurial-devel/merge_requests/1 (it also makes use of the new high-level `PySet`, which I can submit independently). I did not submit it yet, because I've been slow on rebasing / testing against Py2 and Py3 with consistent results. You shot first :-) Note that I don't care much which version lands at the end of the day. Regards, On 10/13/19 11:47 AM, Yuya Nishihara wrote: > # HG changeset patch > # User Yuya Nishihara > # Date 1570954064 -32400 > # Sun Oct 13 17:07:44 2019 +0900 > # Node ID 6c8410bd4ce786ceca53986514a1fbda5f097f2d > # Parent 2d7671cc1d717f3ed3890e47324e4ed479529466 > rust-cpython: leverage upstreamed py_capsule_fn!() macro Side remark: at some point I'd like to switch the Index capsule to the array-of-functions-and-constants style, as in https://dgrunwald.github.io/rust-cpython/doc/cpython/struct.PyCapsule.html#using-a-capsule-defined-in-another-extension-module This is how all capsules defined in the Python standard library actually work. > > diff --git a/rust/hg-cpython/src/cindex.rs b/rust/hg-cpython/src/cindex.rs > --- a/rust/hg-cpython/src/cindex.rs > +++ b/rust/hg-cpython/src/cindex.rs > @@ -10,18 +10,20 @@ > //! Ideally, we should use an Index entirely implemented in Rust, > //! but this will take some time to get there. > > -use crate::python_sys::{self, PyCapsule_Import}; > -use cpython::{PyClone, PyErr, PyObject, PyResult, Python}; > +use crate::python_sys; > +use cpython::{PyClone, PyObject, PyResult, Python}; > use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION}; > use libc::c_int; > -use std::ffi::CStr; > -use std::mem::transmute; > > -type IndexParentsFn = unsafe extern "C" fn( > -index: *mut python_sys::PyObject, > -rev: c_int, > -ps: *mut [c_int; 2], > -) -> c_int; > +py_capsule_fn!( > +from mercurial.cext.parsers import index_get_parents_CAPI > +as get_parents_capi > +signature ( > +index: *mut python_sys::PyObject, Here you can directly use RawPyObject: index: *mut RawPyObject, see https://github.com/dgrunwald/rust-cpython/commit/c5cfd32cf05005e3ad515063c9ca14100362eb93 the same would apply for other capsules, and that means we can completely get rid of the dependency to sys_python > +rev: c_int, > +ps: *mut [c_int; 2], > +) -> c_int > +); > > /// A `Graph` backed up by objects and functions from revlog.c > /// > @@ -57,14 +59,14 @@ type IndexParentsFn = unsafe extern "C" > /// mechanisms in other contexts. > pub struct Index { > index: PyObject, > -parents: IndexParentsFn, > +parents: get_parents_capi::CapsuleFn, > } > > impl Index { > pub fn new(py: Python, index: PyObject) -> PyResult { > Ok(Index { > index: index, > -parents: decapsule_parents_fn(py)?, > +parents: get_parents_capi::retrieve(py)?, > }) > } > } > @@ -99,31 +101,3 @@ impl Graph for Index { > } > } > } > - > -/// Return the `index_get_parents` function of the parsers C Extension > module. > -/// > -/// A pointer to the function is stored in the `parsers` module as a > -/// standard [Python capsule](https://docs.python.org/2/c-api/capsule.html). > -/// > -/// This function retrieves the capsule and casts the function pointer > -/// > -/// Casting function pointers is one of the rare cases of > -/// legitimate use cases of `mem::transmute()` (see > -/// https://doc.rust-lang.org/std/mem/fn.transmute.html of > -/// `mem::transmute()`. > -/// It is inappropriate for architectures where > -/// function and data pointer sizes differ (so-called "Harvard > -/// architectures"), but these are nowadays mostly DSPs > -/// and microcontrollers, hence out of our scope. > -fn decapsule_parents_fn(py: Python) -> PyResult { > -unsafe { > -let caps_name = CStr::from_bytes_with_nul_unchecked( > -b"mercurial.cext.parsers.index_get_parents_CAPI\0", > -); > -let from_caps = PyCapsule_Import(caps_name.as_ptr(), 0); > -if from_caps.is_null() { > -return Err(PyErr::fetch(py)); > -} > -Ok(transmute(from_caps)) > -} > -} > diff --git a/rust/hg-cpython/src/dirstate.rs b/rust/hg-cpython/src/dirstate.rs > --- a/rust/hg-cpython/src/dirstate.rs > +++ b/rust/hg-cpython/src/dirstate.rs > @@ -15,7 +15,7 @@ mod dirs_multiset; > mod dirstate_map; > > use crate::dirstate::{dirs_multiset::Dirs, dirstate_map::DirstateMap}; > -use crate::python_sys::{self, PyCapsule_Import}; > +use crate::python_sys; > use cpython::{ >
[PATCH] dirs: remove mutable string optimization at all
# HG changeset patch # User Yuya Nishihara # Date 1570964769 -32400 # Sun Oct 13 20:06:09 2019 +0900 # Node ID 87dfcdb8394e377049b5a337585309ae4c652c7d # Parent ce20b870041fc4d6ba6989acbb9373797ce9b3d6 dirs: remove mutable string optimization at all As far as I can see, the optimization trick has been dead since 42e89b87ca79 "dirs: speed up by storing number of direct children per dir". After 42e89b87ca79, the key variable is cleared to NULL at every iteration. diff --git a/mercurial/cext/dirs.c b/mercurial/cext/dirs.c --- a/mercurial/cext/dirs.c +++ b/mercurial/cext/dirs.c @@ -63,46 +63,18 @@ static int _addpath(PyObject *dirs, PyOb * "protocol" such as mutating immutable objects. But since we only * mutate objects created in this function or in other well-defined * locations, the references are known so these violations should go - * unnoticed. The code for adjusting the length of a PyBytesObject is - * essentially a minimal version of _PyBytes_Resize. */ + * unnoticed. */ while ((pos = _finddir(cpath, pos - 1)) != -1) { PyObject *val; - if (pos < 2) { - key = PyBytes_FromStringAndSize(cpath, pos); - if (key == NULL) - goto bail; - } else { - /* It's likely that every prefix already has an entry - in our dict. Try to avoid allocating and - deallocating a string for each prefix we check. */ - if (key != NULL) - ((PyBytesObject *)key)->ob_shash = -1; - else { - /* We know pos >= 2, so we won't get a small -* shared string. */ - key = PyBytes_FromStringAndSize(cpath, pos); - if (key == NULL) - goto bail; - } - /* Py_SIZE(o) refers to the ob_size member of -* the struct. Yes, assigning to what looks -* like a function seems wrong. */ - Py_SIZE(key) = pos; - ((PyBytesObject *)key)->ob_sval[pos] = '\0'; - } + key = PyBytes_FromStringAndSize(cpath, pos); + if (key == NULL) + goto bail; val = PyDict_GetItem(dirs, key); if (val != NULL) { PYLONG_VALUE(val) += 1; - if (pos < 2) { - /* This was a short string, so we -* probably got a small shared string -* we can't mutate on the next loop -* iteration. Clear it. -*/ - Py_CLEAR(key); - } + Py_CLEAR(key); break; } ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 2] perf: introduce a `--iteration` to `perfdirstate`
On Sat, 12 Oct 2019 04:20:42 +0200, Pierre-Yves David wrote: > # HG changeset patch > # User Pierre-Yves David > # Date 1570522984 14400 > # Tue Oct 08 04:23:04 2019 -0400 > # Node ID 992c09636ae9d0543ea621305a71d6f9f77dc7dc > # Parent c88075eb28e3281a4470fde929fbf5a13bda5f8a > # EXP-Topic perf-dirstate > # Available At https://bitbucket.org/octobus/mercurial-devel/ > # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r > 992c09636ae9 > perf: introduce a `--iteration` to `perfdirstate` Fixed some missing b''s and queued, thanks. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Re: [PATCH 1 of 2] patchcopies: give up any optimization based on `introrev`
On Fri, 11 Oct 2019 20:00:58 +0200, Pierre-Yves David wrote: > On 10/11/19 2:02 PM, Yuya Nishihara wrote: > > On Fri, 11 Oct 2019 01:04:12 +0200, Pierre-Yves David wrote: > >> # HG changeset patch > >> # User Pierre-Yves David > >> # Date 1570672173 -7200 > >> # Thu Oct 10 03:49:33 2019 +0200 > >> # Node ID 2477ba483c04067900d1e9f6523b03df68a4d545 > >> # Parent 8ff1ecfadcd110849c47c77e31c92809eea466ab > >> # EXP-Topic patchcopies-regression > >> # Available At https://bitbucket.org/octobus/mercurial-devel/ > >> # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r > >> 2477ba483c04 > >> patchcopies: give up any optimization based on `introrev` > >> > >> Between 8a0136f69027 and d98fb3f42f33, we sped up the search for the > >> introduction revision during path copies. However, further checking show > >> that > >> finding the introduction revision is still expensive and that we are > >> better off > >> without it. So we simply drop it and only rely on the linkrev optimisation. > >> > >> I ran `perfpathcopies` on 6989 pair of revision in the pypy > >> repository (`hg perfhelper-pathcopies`. The result is massively in favor of > >> dropping this condition. The result of the copy tracing are unchanged. > >> > >> Attempt to use a smaller changes preserving linkrev usage were > >> unsuccessful, it > >> can return wrong result. The following changesets broke > >> test-mv-cp-st-diff.t > >> > >> -if not f.isintroducedafter(limit): > >> +if limit >= 0 and f.linkrev() < limit: > >> return None > > > > Sure. I meant comparing linkrevs, not linkrev vs (changelog) rev. If both > > arms were linkrevs, and if the limit pointed to the revision where the > > linkrevs of its files are guaranteed to be the lowest, the comparison > > (e.g. f.linkrev() < repo[limit][path].linkrev()) would work. > > > > My question was whether it would make things fast or not. > > Ha, I understand your proposal better now. > > My testing of the version in this patch versus the "wrong" version using > linkrev too agressively did not show a significant difference (-1%). Do you mean only 1% speedup or measurable speedup on 1% cases? I don't think the former is significant, but the latter could be depending on use cases. > So > I don't it to raise anything better. Can we move forward with this > series and maybe try a different approach later ? Better to leave the _findlimit() function? Or won't it be any useful in your future work? ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 7 of 7] rust-cpython: leverage upstreamed py_capsule_fn!() macro
# HG changeset patch # User Yuya Nishihara # Date 1570954064 -32400 # Sun Oct 13 17:07:44 2019 +0900 # Node ID 6c8410bd4ce786ceca53986514a1fbda5f097f2d # Parent 2d7671cc1d717f3ed3890e47324e4ed479529466 rust-cpython: leverage upstreamed py_capsule_fn!() macro diff --git a/rust/hg-cpython/src/cindex.rs b/rust/hg-cpython/src/cindex.rs --- a/rust/hg-cpython/src/cindex.rs +++ b/rust/hg-cpython/src/cindex.rs @@ -10,18 +10,20 @@ //! Ideally, we should use an Index entirely implemented in Rust, //! but this will take some time to get there. -use crate::python_sys::{self, PyCapsule_Import}; -use cpython::{PyClone, PyErr, PyObject, PyResult, Python}; +use crate::python_sys; +use cpython::{PyClone, PyObject, PyResult, Python}; use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION}; use libc::c_int; -use std::ffi::CStr; -use std::mem::transmute; -type IndexParentsFn = unsafe extern "C" fn( -index: *mut python_sys::PyObject, -rev: c_int, -ps: *mut [c_int; 2], -) -> c_int; +py_capsule_fn!( +from mercurial.cext.parsers import index_get_parents_CAPI +as get_parents_capi +signature ( +index: *mut python_sys::PyObject, +rev: c_int, +ps: *mut [c_int; 2], +) -> c_int +); /// A `Graph` backed up by objects and functions from revlog.c /// @@ -57,14 +59,14 @@ type IndexParentsFn = unsafe extern "C" /// mechanisms in other contexts. pub struct Index { index: PyObject, -parents: IndexParentsFn, +parents: get_parents_capi::CapsuleFn, } impl Index { pub fn new(py: Python, index: PyObject) -> PyResult { Ok(Index { index: index, -parents: decapsule_parents_fn(py)?, +parents: get_parents_capi::retrieve(py)?, }) } } @@ -99,31 +101,3 @@ impl Graph for Index { } } } - -/// Return the `index_get_parents` function of the parsers C Extension module. -/// -/// A pointer to the function is stored in the `parsers` module as a -/// standard [Python capsule](https://docs.python.org/2/c-api/capsule.html). -/// -/// This function retrieves the capsule and casts the function pointer -/// -/// Casting function pointers is one of the rare cases of -/// legitimate use cases of `mem::transmute()` (see -/// https://doc.rust-lang.org/std/mem/fn.transmute.html of -/// `mem::transmute()`. -/// It is inappropriate for architectures where -/// function and data pointer sizes differ (so-called "Harvard -/// architectures"), but these are nowadays mostly DSPs -/// and microcontrollers, hence out of our scope. -fn decapsule_parents_fn(py: Python) -> PyResult { -unsafe { -let caps_name = CStr::from_bytes_with_nul_unchecked( -b"mercurial.cext.parsers.index_get_parents_CAPI\0", -); -let from_caps = PyCapsule_Import(caps_name.as_ptr(), 0); -if from_caps.is_null() { -return Err(PyErr::fetch(py)); -} -Ok(transmute(from_caps)) -} -} diff --git a/rust/hg-cpython/src/dirstate.rs b/rust/hg-cpython/src/dirstate.rs --- a/rust/hg-cpython/src/dirstate.rs +++ b/rust/hg-cpython/src/dirstate.rs @@ -15,7 +15,7 @@ mod dirs_multiset; mod dirstate_map; use crate::dirstate::{dirs_multiset::Dirs, dirstate_map::DirstateMap}; -use crate::python_sys::{self, PyCapsule_Import}; +use crate::python_sys; use cpython::{ exc, PyBytes, PyDict, PyErr, PyModule, PyObject, PyResult, PySequence, Python, @@ -26,8 +26,6 @@ use hg::{ }; use libc::{c_char, c_int}; use std::convert::TryFrom; -use std::ffi::CStr; -use std::mem::transmute; // C code uses a custom `dirstate_tuple` type, checks in multiple instances // for this type, and raises a Python `Exception` if the check does not pass. @@ -35,34 +33,23 @@ use std::mem::transmute; // would be a good idea in the near future to remove it entirely to allow // for a pure Python tuple of the same effective structure to be used, // rendering this type and the capsule below useless. -type MakeDirstateTupleFn = unsafe extern "C" fn( -state: c_char, -mode: c_int, -size: c_int, -mtime: c_int, -) -> *mut python_sys::PyObject; - -// This is largely a copy/paste from cindex.rs, pending the merge of a -// `py_capsule_fn!` macro in the rust-cpython project: -// https://github.com/dgrunwald/rust-cpython/pull/169 -fn decapsule_make_dirstate_tuple(py: Python) -> PyResult { -unsafe { -let caps_name = CStr::from_bytes_with_nul_unchecked( -b"mercurial.cext.parsers.make_dirstate_tuple_CAPI\0", -); -let from_caps = PyCapsule_Import(caps_name.as_ptr(), 0); -if from_caps.is_null() { -return Err(PyErr::fetch(py)); -} -Ok(transmute(from_caps)) -} -} +py_capsule_fn!( +from mercurial.cext.parsers import make_dirstate_tuple_CAPI +as make_dirstate_tuple_capi +signature ( +state: c_char, +mode: c_int, +size: c_int, +
[PATCH 6 of 7] rust-cpython: bump cpython crates to 0.3
# HG changeset patch # User Yuya Nishihara # Date 1570953909 -32400 # Sun Oct 13 17:05:09 2019 +0900 # Node ID 2d7671cc1d717f3ed3890e47324e4ed479529466 # Parent 88cde8b3df606c060c32de2002a2008f030a10c5 rust-cpython: bump cpython crates to 0.3 Unblocks py_capsule_fn!(). diff --git a/rust/Cargo.lock b/rust/Cargo.lock --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -33,13 +33,13 @@ dependencies = [ [[package]] name = "cpython" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index; dependencies = [ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "python27-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "python27-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "python3-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -63,11 +63,11 @@ dependencies = [ name = "hg-cpython" version = "0.1.0" dependencies = [ - "cpython 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cpython 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hg-core 0.1.0", "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "python27-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "python27-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "python3-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -100,7 +100,7 @@ source = "registry+https://github.com/ru [[package]] name = "python27-sys" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index; dependencies = [ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", @@ -109,7 +109,7 @@ dependencies = [ [[package]] name = "python3-sys" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index; dependencies = [ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", @@ -304,14 +304,14 @@ source = "registry+https://github.com/ru "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum cpython 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b489034e723e7f5109fecd19b719e664f89ef925be785885252469e9822fa940" +"checksum cpython 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85532c648315aeb0829ad216a6a29aa3212cf9319bc7f6daf1404aa0bdd1485f" "checksum fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81f7f8eb465745ea9b02e2704612a9946a59fa40572086c6fd49d6ddcf30bf31" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum python27-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "56114c37d4dca82526d74009df7782a28c871ac9d36b19d4cb9e67672258527e" -"checksum python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "61e4aac43f833fd637e429506cb2ac9d7df672c4b68f2eaaa163649b7fdc0444" +"checksum python27-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "372555e88a6bc8109eb641380240dc8d25a128fc48363ec9075664daadffdd5b" +"checksum python3-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3a8ebed3f1201fda179f3960609dbbc10cd8c75e9f2afcb03788278f367d8ea" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a6321f5f8c7411e5be7eed4b" diff --git
[PATCH 5 of 7] rust-cpython: turn inline comments into non-doc comments
# HG changeset patch # User Yuya Nishihara # Date 1570953746 -32400 # Sun Oct 13 17:02:26 2019 +0900 # Node ID 88cde8b3df606c060c32de2002a2008f030a10c5 # Parent 8ba14080af7216e711666457c2c068661ae3a97e rust-cpython: turn inline comments into non-doc comments diff --git a/rust/hg-cpython/src/dirstate.rs b/rust/hg-cpython/src/dirstate.rs --- a/rust/hg-cpython/src/dirstate.rs +++ b/rust/hg-cpython/src/dirstate.rs @@ -29,12 +29,12 @@ use std::convert::TryFrom; use std::ffi::CStr; use std::mem::transmute; -/// C code uses a custom `dirstate_tuple` type, checks in multiple instances -/// for this type, and raises a Python `Exception` if the check does not pass. -/// Because this type differs only in name from the regular Python tuple, it -/// would be a good idea in the near future to remove it entirely to allow -/// for a pure Python tuple of the same effective structure to be used, -/// rendering this type and the capsule below useless. +// C code uses a custom `dirstate_tuple` type, checks in multiple instances +// for this type, and raises a Python `Exception` if the check does not pass. +// Because this type differs only in name from the regular Python tuple, it +// would be a good idea in the near future to remove it entirely to allow +// for a pure Python tuple of the same effective structure to be used, +// rendering this type and the capsule below useless. type MakeDirstateTupleFn = unsafe extern "C" fn( state: c_char, mode: c_int, @@ -42,9 +42,9 @@ type MakeDirstateTupleFn = unsafe extern mtime: c_int, ) -> *mut python_sys::PyObject; -/// This is largely a copy/paste from cindex.rs, pending the merge of a -/// `py_capsule_fn!` macro in the rust-cpython project: -/// https://github.com/dgrunwald/rust-cpython/pull/169 +// This is largely a copy/paste from cindex.rs, pending the merge of a +// `py_capsule_fn!` macro in the rust-cpython project: +// https://github.com/dgrunwald/rust-cpython/pull/169 fn decapsule_make_dirstate_tuple(py: Python) -> PyResult { unsafe { let caps_name = CStr::from_bytes_with_nul_unchecked( ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 4 of 7] rust-cpython: fix signature of make_dirstate_tuple()
# HG changeset patch # User Yuya Nishihara # Date 1570953670 -32400 # Sun Oct 13 17:01:10 2019 +0900 # Node ID 8ba14080af7216e711666457c2c068661ae3a97e # Parent 63a1df3aac72e67667eb7210f364f4b2d892b06f rust-cpython: fix signature of make_dirstate_tuple() Fortunately, the layout of PyObject {} is compatible with a C pointer, but we shouldn't rely on that. This also fixes the handling of NULL pointer. diff --git a/rust/hg-cpython/src/dirstate.rs b/rust/hg-cpython/src/dirstate.rs --- a/rust/hg-cpython/src/dirstate.rs +++ b/rust/hg-cpython/src/dirstate.rs @@ -15,7 +15,7 @@ mod dirs_multiset; mod dirstate_map; use crate::dirstate::{dirs_multiset::Dirs, dirstate_map::DirstateMap}; -use crate::python_sys::PyCapsule_Import; +use crate::python_sys::{self, PyCapsule_Import}; use cpython::{ exc, PyBytes, PyDict, PyErr, PyModule, PyObject, PyResult, PySequence, Python, @@ -40,7 +40,7 @@ type MakeDirstateTupleFn = unsafe extern mode: c_int, size: c_int, mtime: c_int, -) -> PyObject; +) -> *mut python_sys::PyObject; /// This is largely a copy/paste from cindex.rs, pending the merge of a /// `py_capsule_fn!` macro in the rust-cpython project: @@ -75,10 +75,11 @@ pub fn make_dirstate_tuple( // just do a naive enum cast. let state_code: u8 = state.into(); -unsafe { +let maybe_obj = unsafe { let ptr = make(state_code as c_char, mode, size, mtime); -Ok(ptr) -} +PyObject::from_owned_ptr_opt(py, ptr) +}; +maybe_obj.ok_or_else(|| PyErr::fetch(py)) } pub fn extract_dirstate(py: Python, dmap: ) -> Result { ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 3 of 7] rust-cpython: mark capsule function as unsafe
# HG changeset patch # User Yuya Nishihara # Date 1570953495 -32400 # Sun Oct 13 16:58:15 2019 +0900 # Node ID 63a1df3aac72e67667eb7210f364f4b2d892b06f # Parent 00cd8123f876e03a3af2660c6cf4ba1a77b2bee3 rust-cpython: mark capsule function as unsafe diff --git a/rust/hg-cpython/src/dirstate.rs b/rust/hg-cpython/src/dirstate.rs --- a/rust/hg-cpython/src/dirstate.rs +++ b/rust/hg-cpython/src/dirstate.rs @@ -35,7 +35,7 @@ use std::mem::transmute; /// would be a good idea in the near future to remove it entirely to allow /// for a pure Python tuple of the same effective structure to be used, /// rendering this type and the capsule below useless. -type MakeDirstateTupleFn = extern "C" fn( +type MakeDirstateTupleFn = unsafe extern "C" fn( state: c_char, mode: c_int, size: c_int, @@ -74,7 +74,11 @@ pub fn make_dirstate_tuple( // because Into has a specific implementation while `as c_char` would // just do a naive enum cast. let state_code: u8 = state.into(); -Ok(make(state_code as c_char, mode, size, mtime)) + +unsafe { +let ptr = make(state_code as c_char, mode, size, mtime); +Ok(ptr) +} } pub fn extract_dirstate(py: Python, dmap: ) -> Result { ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[PATCH 2 of 7] rust-cpython: add wrapper around decapsule_make_dirstate_tuple()
# HG changeset patch # User Yuya Nishihara # Date 1570953317 -32400 # Sun Oct 13 16:55:17 2019 +0900 # Node ID 00cd8123f876e03a3af2660c6cf4ba1a77b2bee3 # Parent 6ecc771edbad738c634b50846de1943ea7d34d9e rust-cpython: add wrapper around decapsule_make_dirstate_tuple() There are a couple of safety issues. First, the returned function pointer must be unsafe. Second, its return value must be a raw pointer (i.e. python27_sys::PyObject), not a cpython::PyObject. The wrapper function will address these issues. diff --git a/rust/hg-cpython/src/dirstate.rs b/rust/hg-cpython/src/dirstate.rs --- a/rust/hg-cpython/src/dirstate.rs +++ b/rust/hg-cpython/src/dirstate.rs @@ -45,9 +45,7 @@ type MakeDirstateTupleFn = extern "C" fn /// This is largely a copy/paste from cindex.rs, pending the merge of a /// `py_capsule_fn!` macro in the rust-cpython project: /// https://github.com/dgrunwald/rust-cpython/pull/169 -pub fn decapsule_make_dirstate_tuple( -py: Python, -) -> PyResult { +fn decapsule_make_dirstate_tuple(py: Python) -> PyResult { unsafe { let caps_name = CStr::from_bytes_with_nul_unchecked( b"mercurial.cext.parsers.make_dirstate_tuple_CAPI\0", @@ -60,6 +58,25 @@ pub fn decapsule_make_dirstate_tuple( } } +pub fn make_dirstate_tuple( +py: Python, +entry: , +) -> PyResult { +let make = decapsule_make_dirstate_tuple(py)?; + +let { +state, +mode, +size, +mtime, +} = entry; +// Explicitly go through u8 first, then cast to platform-specific `c_char` +// because Into has a specific implementation while `as c_char` would +// just do a naive enum cast. +let state_code: u8 = state.into(); +Ok(make(state_code as c_char, mode, size, mtime)) +} + pub fn extract_dirstate(py: Python, dmap: ) -> Result { dmap.items(py) .iter() diff --git a/rust/hg-cpython/src/dirstate/dirstate_map.rs b/rust/hg-cpython/src/dirstate/dirstate_map.rs --- a/rust/hg-cpython/src/dirstate/dirstate_map.rs +++ b/rust/hg-cpython/src/dirstate/dirstate_map.rs @@ -16,11 +16,10 @@ use cpython::{ exc, ObjectProtocol, PyBool, PyBytes, PyClone, PyDict, PyErr, PyObject, PyResult, PyTuple, Python, PythonObject, ToPyObject, }; -use libc::c_char; use crate::{ dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator}, -dirstate::{decapsule_make_dirstate_tuple, dirs_multiset::Dirs}, +dirstate::{dirs_multiset::Dirs, make_dirstate_tuple}, ref_sharing::{PyLeakedRef, PySharedRefCell}, }; use hg::{ @@ -66,15 +65,7 @@ py_class!(pub class DirstateMap |py| { let key = key.extract::(py)?; match self.inner_shared(py).borrow().get(HgPath::new(key.data(py))) { Some(entry) => { -// Explicitly go through u8 first, then cast to -// platform-specific `c_char`. -let state: u8 = entry.state.into(); -Ok(Some(decapsule_make_dirstate_tuple(py)?( -state as c_char, -entry.mode, -entry.size, -entry.mtime, -))) +Ok(Some(make_dirstate_tuple(py, entry)?)) }, None => Ok(default) } @@ -303,15 +294,7 @@ py_class!(pub class DirstateMap |py| { let key = HgPath::new(key.data(py)); match self.inner_shared(py).borrow().get(key) { Some(entry) => { -// Explicitly go through u8 first, then cast to -// platform-specific `c_char`. -let state: u8 = entry.state.into(); -Ok(decapsule_make_dirstate_tuple(py)?( -state as c_char, -entry.mode, -entry.size, -entry.mtime, -)) +Ok(make_dirstate_tuple(py, entry)?) }, None => Err(PyErr::new::( py, @@ -483,18 +466,9 @@ impl DirstateMap { res: (, ), ) -> PyResult> { let (f, entry) = res; - -// Explicitly go through u8 first, then cast to -// platform-specific `c_char`. -let state: u8 = entry.state.into(); Ok(Some(( PyBytes::new(py, f.as_ref()), -decapsule_make_dirstate_tuple(py)?( -state as c_char, -entry.mode, -entry.size, -entry.mtime, -), +make_dirstate_tuple(py, entry)?, ))) } } diff --git a/rust/hg-cpython/src/parsers.rs b/rust/hg-cpython/src/parsers.rs --- a/rust/hg-cpython/src/parsers.rs +++ b/rust/hg-cpython/src/parsers.rs @@ -15,15 +15,13 @@ use cpython::{ PythonObject, ToPyObject, }; use hg::{ -pack_dirstate, parse_dirstate, utils::hg_path::HgPathBuf, DirstateEntry, +pack_dirstate, parse_dirstate, utils::hg_path::HgPathBuf, DirstatePackError, DirstateParents,
[PATCH 1 of 7] rust-cpython: alias python(27|3)_sys globally
# HG changeset patch # User Yuya Nishihara # Date 1570952770 -32400 # Sun Oct 13 16:46:10 2019 +0900 # Node ID 6ecc771edbad738c634b50846de1943ea7d34d9e # Parent dbe969ca04b9711aa3b244b2dcea9b9925bab960 rust-cpython: alias python(27|3)_sys globally diff --git a/rust/hg-cpython/src/cindex.rs b/rust/hg-cpython/src/cindex.rs --- a/rust/hg-cpython/src/cindex.rs +++ b/rust/hg-cpython/src/cindex.rs @@ -9,15 +9,11 @@ //! //! Ideally, we should use an Index entirely implemented in Rust, //! but this will take some time to get there. -#[cfg(feature = "python27")] -use python27_sys as python_sys; -#[cfg(feature = "python3")] -use python3_sys as python_sys; +use crate::python_sys::{self, PyCapsule_Import}; use cpython::{PyClone, PyErr, PyObject, PyResult, Python}; use hg::{Graph, GraphError, Revision, WORKING_DIRECTORY_REVISION}; use libc::c_int; -use python_sys::PyCapsule_Import; use std::ffi::CStr; use std::mem::transmute; diff --git a/rust/hg-cpython/src/dirstate.rs b/rust/hg-cpython/src/dirstate.rs --- a/rust/hg-cpython/src/dirstate.rs +++ b/rust/hg-cpython/src/dirstate.rs @@ -9,10 +9,13 @@ //! `hg-core` package. //! //! From Python, this will be seen as `mercurial.rustext.dirstate` + mod copymap; mod dirs_multiset; mod dirstate_map; + use crate::dirstate::{dirs_multiset::Dirs, dirstate_map::DirstateMap}; +use crate::python_sys::PyCapsule_Import; use cpython::{ exc, PyBytes, PyDict, PyErr, PyModule, PyObject, PyResult, PySequence, Python, @@ -22,10 +25,6 @@ use hg::{ StateMap, }; use libc::{c_char, c_int}; -#[cfg(feature = "python27")] -use python27_sys::PyCapsule_Import; -#[cfg(feature = "python3")] -use python3_sys::PyCapsule_Import; use std::convert::TryFrom; use std::ffi::CStr; use std::mem::transmute; diff --git a/rust/hg-cpython/src/lib.rs b/rust/hg-cpython/src/lib.rs --- a/rust/hg-cpython/src/lib.rs +++ b/rust/hg-cpython/src/lib.rs @@ -24,6 +24,11 @@ #[macro_use] extern crate cpython; +#[cfg(feature = "python27")] +use python27_sys as python_sys; +#[cfg(feature = "python3")] +use python3_sys as python_sys; + pub mod ancestors; mod cindex; mod conversion; ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D7081: tests: open file in binary mode in test-upgrade-repo.t
Closed by commit rHG86b26f20146d: tests: open file in binary mode in test-upgrade-repo.t (authored by mharbison72). This revision was automatically updated to reflect the committed changes. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D7081?vs=17123=17126 CHANGES SINCE LAST ACTION https://phab.mercurial-scm.org/D7081/new/ REVISION DETAIL https://phab.mercurial-scm.org/D7081 AFFECTED FILES tests/test-upgrade-repo.t CHANGE DETAILS diff --git a/tests/test-upgrade-repo.t b/tests/test-upgrade-repo.t --- a/tests/test-upgrade-repo.t +++ b/tests/test-upgrade-repo.t @@ -452,9 +452,9 @@ >>> from __future__ import absolute_import, print_function >>> import random >>> random.seed(0) # have a reproducible content - >>> with open("f2", "w") as f: + >>> with open("f2", "wb") as f: ... for i in range(10): - ... f.write("%d\n" % random.randint(10, 99)) and None + ... f.write(b"%d\n" % random.randint(10, 99)) and None $ hg -q commit -A -m 'add f2' make sure we have a .d file To: mharbison72, #hg-reviewers, indygreg Cc: indygreg, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D7080: hghave: use a native string to invoke the `black` command
Closed by commit rHG138ac8cbce60: hghave: use a native string to invoke the `black` command (authored by mharbison72). This revision was automatically updated to reflect the committed changes. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D7080?vs=17122=17125 CHANGES SINCE LAST ACTION https://phab.mercurial-scm.org/D7080/new/ REVISION DETAIL https://phab.mercurial-scm.org/D7080 AFFECTED FILES tests/hghave.py CHANGE DETAILS diff --git a/tests/hghave.py b/tests/hghave.py --- a/tests/hghave.py +++ b/tests/hghave.py @@ -984,8 +984,8 @@ @check('grey', 'grey, the fork of the black formatter for python') def has_black(): # use that to actual black as soon as possible -# blackcmd = b'black --version' -blackcmd = b'python3 $RUNTESTDIR/../contrib/grey.py --version' +# blackcmd = 'black --version' +blackcmd = 'python3 $RUNTESTDIR/../contrib/grey.py --version' # version_regex = b'black, version \d' version_regex = b'grey.py, version \d' return matchoutput(blackcmd, version_regex) To: mharbison72, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D7079: py3: convert cwd to native string when running `fix`
Closed by commit rHG2d1f9880af1b: py3: convert cwd to native string when running `fix` (authored by mharbison72). This revision was automatically updated to reflect the committed changes. REPOSITORY rHG Mercurial CHANGES SINCE LAST UPDATE https://phab.mercurial-scm.org/D7079?vs=17121=17124 CHANGES SINCE LAST ACTION https://phab.mercurial-scm.org/D7079/new/ REVISION DETAIL https://phab.mercurial-scm.org/D7079 AFFECTED FILES hgext/fix.py CHANGE DETAILS diff --git a/hgext/fix.py b/hgext/fix.py --- a/hgext/fix.py +++ b/hgext/fix.py @@ -631,7 +631,7 @@ proc = subprocess.Popen( procutil.tonativestr(command), shell=True, -cwd=repo.root, +cwd=procutil.tonativestr(repo.root), stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, To: mharbison72, #hg-reviewers, indygreg Cc: mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel