D11653: chistedit: rename a confusingly named variable

2021-10-12 Thread martinvonz (Martin von Zweigbergk)
martinvonz created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  I would expect `ctxs` contain instances of some class from the
  `context` module but it actually contains instances of `histeditrule`.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11653

AFFECTED FILES
  hgext/histedit.py

CHANGE DETAILS

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1716,11 +1716,11 @@
 _(b'%s is not an ancestor of working directory') % short(root)
 )
 
-ctxs = []
+rules = []
 for i, r in enumerate(revs):
-ctxs.append(histeditrule(ui, repo[r], i))
+rules.append(histeditrule(ui, repo[r], i))
 with util.with_lc_ctype():
-rc = curses.wrapper(functools.partial(_chisteditmain, repo, ctxs))
+rc = curses.wrapper(functools.partial(_chisteditmain, repo, rules))
 curses.echo()
 curses.endwin()
 if rc is False:



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D11652: chistedit: remove some local variable and access state on self instead

2021-10-12 Thread martinvonz (Martin von Zweigbergk)
martinvonz created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  Now that we've replaced the state dict by a class, some of the local
  variables that just do `foo = self.foo` seem unnecessary.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11652

AFFECTED FILES
  hgext/histedit.py

CHANGE DETAILS

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1256,9 +1256,7 @@
 def render_commit(self, win):
 """Renders the commit window that shows the log of the current selected
 commit"""
-pos = self.pos
-rules = self.rules
-rule = rules[pos]
+rule = self.rules[self.pos]
 
 ctx = rule.ctx
 win.box()
@@ -1345,19 +1343,16 @@
 }
 
 def render_rules(self, rulesscr):
-rules = self.rules
-pos = self.pos
-selected = self.selected
 start = self.modes[MODE_RULES][b'line_offset']
 
-conflicts = [r.ctx for r in rules if r.conflicts]
+conflicts = [r.ctx for r in self.rules if r.conflicts]
 if len(conflicts) > 0:
 line = b"potential conflict in %s" % b','.join(
 map(pycompat.bytestr, conflicts)
 )
 addln(rulesscr, -1, 0, line, curses.color_pair(COLOR_WARN))
 
-for y, rule in enumerate(rules[start:]):
+for y, rule in enumerate(self.rules[start:]):
 if y >= self.page_height:
 break
 if len(rule.conflicts) > 0:
@@ -1365,10 +1360,10 @@
 else:
 rulesscr.addstr(y, 0, b" ", curses.COLOR_BLACK)
 
-if y + start == selected:
+if y + start == self.selected:
 rollcolor = COLOR_ROLL_SELECTED
 addln(rulesscr, y, 2, rule, curses.color_pair(COLOR_SELECTED))
-elif y + start == pos:
+elif y + start == self.pos:
 rollcolor = COLOR_ROLL_CURRENT
 addln(
 rulesscr,
@@ -1424,9 +1419,7 @@
 This takes the current state and based on the current character input 
from
 the user we change the state.
 """
-selected = self.selected
 oldpos = self.pos
-rules = self.rules
 
 if ch in (curses.KEY_RESIZE, b"KEY_RESIZE"):
 return E_RESIZE
@@ -1442,26 +1435,26 @@
 if action is None:
 return
 if action in (b'down', b'move-down'):
-newpos = min(oldpos + 1, len(rules) - 1)
+newpos = min(oldpos + 1, len(self.rules) - 1)
 self.move_cursor(oldpos, newpos)
-if selected is not None or action == b'move-down':
+if self.selected is not None or action == b'move-down':
 self.swap(oldpos, newpos)
 elif action in (b'up', b'move-up'):
 newpos = max(0, oldpos - 1)
 self.move_cursor(oldpos, newpos)
-if selected is not None or action == b'move-up':
+if self.selected is not None or action == b'move-up':
 self.swap(oldpos, newpos)
 elif action == b'next-action':
 self.cycle_action(oldpos, next=True)
 elif action == b'prev-action':
 self.cycle_action(oldpos, next=False)
 elif action == b'select':
-selected = oldpos if selected is None else None
-self.make_selection(selected)
-elif action == b'goto' and int(ch) < len(rules) and len(rules) <= 10:
-newrule = next((r for r in rules if r.origpos == int(ch)))
+self.selected = oldpos if self.selected is None else None
+self.make_selection(self.selected)
+elif action == b'goto' and int(ch) < len(self.rules) <= 10:
+newrule = next((r for r in self.rules if r.origpos == int(ch)))
 self.move_cursor(oldpos, newrule.pos)
-if selected is not None:
+if self.selected is not None:
 self.swap(oldpos, newrule.pos)
 elif action.startswith(b'action-'):
 self.change_action(oldpos, action[7:])
@@ -1549,16 +1542,14 @@
 
 def change_action(self, pos, action):
 """Change the action state on the given position to the new action"""
-rules = self.rules
-assert 0 <= pos < len(rules)
-rules[pos].action = action
+assert 0 <= pos < len(self.rules)
+self.rules[pos].action = action
 
 def cycle_action(self, pos, next=False):
 """Changes the action state the next or the previous action from
 the action list"""
-rules = self.rules
-assert 0 <= pos < len(rules)
-current = rules[pos].action
+assert 0 <= pos < len(self.rules)
+current = self.rules[pos].action
 
 assert current in KEY_LIST
 



To: martinvonz, 

mercurial-devel | Failed pipeline for branch/default | caafdc0d

2021-10-12 Thread Heptapod


Pipeline #27697 has failed!

Project: mercurial-devel ( https://foss.heptapod.net/mercurial/mercurial-devel )
Branch: branch/default ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/commits/branch/default )

Commit: caafdc0d ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/commit/caafdc0d059d9a8ea4f3871ff06bbfdae3ef738a
 )
Commit Message: rhg: handle null changelog and manifest revisio...
Commit Author: Arseniy Alekseyev

Pipeline #27697 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/pipelines/27697 ) 
triggered by Administrator ( https://foss.heptapod.net/root )
had 9 failed jobs.

Job #253018 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/253018/raw )

Stage: tests
Name: test-py2-chg
Job #253011 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/253011/raw )

Stage: tests
Name: test-py2
Job #253020 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/253020/raw )

Stage: tests
Name: check-pytype-py3
Job #253015 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/253015/raw )

Stage: tests
Name: test-py2-rust
Job #253013 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/253013/raw )

Stage: tests
Name: test-py2-pure
Job #253017 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/253017/raw )

Stage: tests
Name: test-py3-rhg
Job #253007 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/253007/raw )

Stage: tests
Name: checks-py2
Job #253009 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/253009/raw )

Stage: tests
Name: rust-cargo-test-py2
Job #253010 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/253010/raw )

Stage: tests
Name: rust-cargo-test-py3

-- 
You're receiving this email because of your account on foss.heptapod.net.



___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


mercurial@48187: 20 new changesets

2021-10-12 Thread Mercurial Commits
20 new changesets in mercurial:

https://www.mercurial-scm.org/repo/hg/rev/df3021c1f093
changeset:   48168:df3021c1f093
user:Pulkit Goyal <7895pul...@gmail.com>
date:Mon Jul 19 04:11:08 2021 +0530
summary: largefiles: pass current transaction to `lfdirstate.write()`

https://www.mercurial-scm.org/repo/hg/rev/1e98f9b5bc71
changeset:   48169:1e98f9b5bc71
user:Pulkit Goyal <7895pul...@gmail.com>
date:Mon Jul 19 04:12:14 2021 +0530
summary: largefiles: add tr backup for largefilesdirstate

https://www.mercurial-scm.org/repo/hg/rev/941fbaab5aff
changeset:   48170:941fbaab5aff
user:Pulkit Goyal <7895pul...@gmail.com>
date:Mon Jul 19 04:13:50 2021 +0530
summary: largefiles: partially undo 
61e526585b20e2ff15f19497d0451d18fea02db8 and child

https://www.mercurial-scm.org/repo/hg/rev/64b8676f11bb
changeset:   48171:64b8676f11bb
user:Pulkit Goyal <7895pul...@gmail.com>
date:Thu Jun 24 14:23:11 2021 +0530
summary: rhg: fallback if tweakdefaults or statuscopies is enabled with 
status

https://www.mercurial-scm.org/repo/hg/rev/08c8cd2527bc
changeset:   48172:08c8cd2527bc
user:Arseniy Alekseyev 
date:Tue Oct 05 16:09:20 2021 +0100
summary: rhg: in rhg cat cli, fix the long name of the --rev flag

https://www.mercurial-scm.org/repo/hg/rev/1d70fb83ff4a
changeset:   48173:1d70fb83ff4a
user:Sushil khanchi 
date:Wed Oct 06 13:32:07 2021 +0530
summary: hg: let extensions call the func without populating opts keys

https://www.mercurial-scm.org/repo/hg/rev/9ecf802b06e0
changeset:   48174:9ecf802b06e0
user:Pulkit Goyal <7895pul...@gmail.com>
date:Tue Oct 05 18:02:22 2021 +0530
summary: rhg: refactor function to relativize paths in utils

https://www.mercurial-scm.org/repo/hg/rev/707c58880cd0
changeset:   48175:707c58880cd0
user:Pulkit Goyal <7895pul...@gmail.com>
date:Tue Oct 05 18:10:04 2021 +0530
summary: rhg: add relative paths support in `rhg status`

https://www.mercurial-scm.org/repo/hg/rev/38deb65d4441
changeset:   48176:38deb65d4441
user:Pulkit Goyal <7895pul...@gmail.com>
date:Fri Jun 25 15:00:08 2021 +0530
summary: rhg: add ui.plain() and check it before showing relative paths in 
status

https://www.mercurial-scm.org/repo/hg/rev/066cdec8f74f
changeset:   48177:066cdec8f74f
user:Danny Hooper 
date:Thu Sep 02 14:07:55 2021 -0700
summary: fix: add test to demonstrate how many times tools are executed

https://www.mercurial-scm.org/repo/hg/rev/f12a19d03d2c
changeset:   48178:f12a19d03d2c
user:Danny Hooper 
date:Thu Sep 02 14:08:45 2021 -0700
summary: fix: reduce number of tool executions

https://www.mercurial-scm.org/repo/hg/rev/67d14d4e036c
changeset:   48179:67d14d4e036c
user:Matt Harbison 
date:Sun Sep 19 01:23:16 2021 -0400
summary: exewrapper: find the proper python3X.dll in the registry

https://www.mercurial-scm.org/repo/hg/rev/f78d8b8c46d7
changeset:   48180:f78d8b8c46d7
user:Matt Harbison 
date:Sun Sep 19 01:36:37 2021 -0400
summary: setup: stop packaging python3.dll and python3X.dll in the wheel 
distribution

https://www.mercurial-scm.org/repo/hg/rev/c95f6c2d1f4e
changeset:   48181:c95f6c2d1f4e
user:Matt Harbison 
date:Sun Oct 03 20:11:42 2021 -0400
summary: packaging: update the certifi dependency

https://www.mercurial-scm.org/repo/hg/rev/01c3dd208c75
changeset:   48182:01c3dd208c75
user:Simon Sapin 
date:Fri Oct 08 11:06:03 2021 +0200
summary: rust: Make the hg-cpython crate default to Python 3

https://www.mercurial-scm.org/repo/hg/rev/eb8092f9304f
changeset:   48183:eb8092f9304f
user:Simon Sapin 
date:Mon Oct 11 17:31:27 2021 +0200
summary: dirstate-v2: Use "byte sequence" in docs

https://www.mercurial-scm.org/repo/hg/rev/8fae2cc6ee86
changeset:   48184:8fae2cc6ee86
user:Martin von Zweigbergk 
date:Fri Oct 08 13:34:33 2021 -0700
summary: dispatch: don't change error status if flushing stdio fails

https://www.mercurial-scm.org/repo/hg/rev/2f2107c01dee
changeset:   48185:2f2107c01dee
user:Martin von Zweigbergk 
date:Fri Oct 08 13:36:02 2021 -0700
summary: dispatch: ignore failure to flush ui

https://www.mercurial-scm.org/repo/hg/rev/6edc8800dbc3
changeset:   48186:6edc8800dbc3
user:Martin von Zweigbergk 
date:Tue Mar 02 09:33:25 2021 -0800
summary: dispatch: use detailed exit code 250 for keyboard interrupt

https://www.mercurial-scm.org/repo/hg/rev/b669e40fbbd6
changeset:   48187:b669e40fbbd6
bookmark:@
tag: tip
user:Raphaël Gomès 
date:Wed Sep 08 10:47:10 2021 +0200
summary: help: update help text for debug-repair-issue6528

-- 
Repository URL: https://www.mercurial-scm.org/repo/hg
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org

mercurial-devel | Failed pipeline for branch/default | 1f38a623

2021-10-12 Thread Heptapod


Pipeline #27691 has failed!

Project: mercurial-devel ( https://foss.heptapod.net/mercurial/mercurial-devel )
Branch: branch/default ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/commits/branch/default )

Commit: 1f38a623 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/commit/1f38a6234134e30fc2e330acd64253bc22a52ab8
 )
Commit Message: dirstate-v2: Name a constant in the Rust implem...
Commit Author: Simon Sapin ( https://foss.heptapod.net/SimonSapin )

Pipeline #27691 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/pipelines/27691 ) 
triggered by Administrator ( https://foss.heptapod.net/root )
had 5 failed jobs.

Job #252961 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/252961/raw )

Stage: tests
Name: test-py2-rust
Job #252964 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/252964/raw )

Stage: tests
Name: test-py2-chg
Job #252957 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/252957/raw )

Stage: tests
Name: test-py2
Job #252959 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/252959/raw )

Stage: tests
Name: test-py2-pure
Job #252953 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/252953/raw )

Stage: tests
Name: checks-py2

-- 
You're receiving this email because of your account on foss.heptapod.net.



___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D11651: rhg: do not fail when the repo is empty

2021-10-12 Thread aalekseyev (Arseniy Alekseyev)
aalekseyev created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11651

AFFECTED FILES
  rust/hg-core/src/revlog/revlog.rs
  rust/hg-core/src/vfs.rs
  tests/test-empty-manifest-index.t

CHANGE DETAILS

diff --git a/tests/test-empty-manifest-index.t 
b/tests/test-empty-manifest-index.t
--- a/tests/test-empty-manifest-index.t
+++ b/tests/test-empty-manifest-index.t
@@ -1,23 +1,27 @@
-Create a repo such that the changelog entry refers to a null manifest node:
+Test null revisions (node , aka rev -1)
+in various circumstances.
+
+Make an empty repo:
 
   $ hg init a
   $ cd a
-  $ hg log
-  $ touch x
-  $ hg add x
-  $ hg commit -m "init"
-  $ hg rm x
-  $ hg commit -q --amend
 
-  $ wc -c < .hg/store/00manifest.i
-  0
-
-Make sure that the manifest can be read (and is empty):
-
-  $ hg --config rhg.on-unsupported=abort files -r .
+  $ hg files -r 
+  [1]
+  $ hg files -r .
   [1]
 
-Test a null changelog rev, too:
+Add an empty commit (this makes the changelog refer to a null manifest node):
+
+
+  $ hg commit -m "init" --config ui.allowemptycommit=true
 
-  $ hg --config rhg.on-unsupported=abort files -r 

+  $ hg files -r .
   [1]
+
+Strip that empty commit (this makes the changelog file empty, as opposed to 
missing):
+
+  $ hg --config 'extensions.strip=' strip . > /dev/null
+
+  $ hg files -r .
+  [1]
diff --git a/rust/hg-core/src/vfs.rs b/rust/hg-core/src/vfs.rs
--- a/rust/hg-core/src/vfs.rs
+++ b/rust/hg-core/src/vfs.rs
@@ -9,6 +9,8 @@
 pub(crate) base: &'a Path,
 }
 
+struct FileNotFound(std::io::Error, PathBuf);
+
 impl Vfs<'_> {
 pub fn join(, relative_path: impl AsRef) -> PathBuf {
 self.base.join(relative_path)
@@ -22,16 +24,41 @@
 std::fs::read().when_reading_file()
 }
 
+fn mmap_open_gen(
+,
+relative_path: impl AsRef,
+) -> Result, HgError> {
+let path = self.join(relative_path);
+let file = match std::fs::File::open() {
+Err(err) => {
+if let ErrorKind::NotFound = err.kind() {
+return Ok(Err(FileNotFound(err, path)));
+};
+return (Err(err)).when_reading_file();
+}
+Ok(file) => file,
+};
+// TODO: what are the safety requirements here?
+let mmap = unsafe { MmapOptions::new().map() }
+.when_reading_file()?;
+Ok(Ok(mmap))
+}
+
+pub fn mmap_open_opt(
+,
+relative_path: impl AsRef,
+) -> Result, HgError> {
+self.mmap_open_gen(relative_path).map(|res| res.ok())
+}
+
 pub fn mmap_open(
 ,
 relative_path: impl AsRef,
 ) -> Result {
-let path = self.base.join(relative_path);
-let file = std::fs::File::open().when_reading_file()?;
-// TODO: what are the safety requirements here?
-let mmap = unsafe { MmapOptions::new().map() }
-.when_reading_file()?;
-Ok(mmap)
+match self.mmap_open_gen(relative_path)? {
+Err(FileNotFound(err, path)) => Err(err).when_reading_file(),
+Ok(res) => Ok(res),
+}
 }
 
 pub fn rename(
diff --git a/rust/hg-core/src/revlog/revlog.rs 
b/rust/hg-core/src/revlog/revlog.rs
--- a/rust/hg-core/src/revlog/revlog.rs
+++ b/rust/hg-core/src/revlog/revlog.rs
@@ -70,15 +70,21 @@
 data_path: Option<>,
 ) -> Result {
 let index_path = index_path.as_ref();
-let index_mmap = repo.store_vfs().mmap_open(_path)?;
+let index = {
+match repo.store_vfs().mmap_open_opt(_path)? {
+None => Index::new(Box::new(vec![])),
+Some(index_mmap) => {
+let version = get_version(_mmap)?;
+if version != 1 {
+// A proper new version should have had a repo/store 
requirement.
+return Err(HgError::corrupted("corrupted revlog"));
+}
 
-let version = get_version(_mmap)?;
-if version != 1 {
-// A proper new version should have had a repo/store requirement.
-return Err(HgError::corrupted("corrupted revlog"));
-}
-
-let index = Index::new(Box::new(index_mmap))?;
+let index = Index::new(Box::new(index_mmap))?;
+Ok(index)
+}
+}
+}?;
 
 let default_data_path = index_path.with_extension("d");
 



To: aalekseyev, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


mercurial-devel | Failed pipeline for branch/default | c2e9d0eb

2021-10-12 Thread Heptapod


Pipeline #27692 has failed!

Project: mercurial-devel ( https://foss.heptapod.net/mercurial/mercurial-devel )
Branch: branch/default ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/commits/branch/default )

Commit: c2e9d0eb ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/commit/c2e9d0eb8db8e736216484880164389ce053e092
 )
Commit Message: rust: update the rust-cpython crate to 0.7.0

T...
Commit Author: Simon Sapin ( https://foss.heptapod.net/SimonSapin )

Pipeline #27692 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/pipelines/27692 ) 
triggered by Administrator ( https://foss.heptapod.net/root )
had 5 failed jobs.

Job #252981 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/252981/raw )

Stage: tests
Name: test-py2-chg
Job #252974 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/252974/raw )

Stage: tests
Name: test-py2
Job #252976 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/252976/raw )

Stage: tests
Name: test-py2-pure
Job #252978 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/252978/raw )

Stage: tests
Name: test-py2-rust
Job #252970 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/252970/raw )

Stage: tests
Name: checks-py2

-- 
You're receiving this email because of your account on foss.heptapod.net.



___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


mercurial-devel | Failed pipeline for branch/default | 506123a0

2021-10-12 Thread Heptapod


Pipeline #27690 has failed!

Project: mercurial-devel ( https://foss.heptapod.net/mercurial/mercurial-devel )
Branch: branch/default ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/commits/branch/default )

Commit: 506123a0 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/commit/506123a0cd7e969a9f39413369e82582a560d66a
 )
Commit Message: dirstate-v2: Replace the 32-bit `mode` field wi...
Commit Author: Simon Sapin ( https://foss.heptapod.net/SimonSapin )

Pipeline #27690 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/pipelines/27690 ) 
triggered by Administrator ( https://foss.heptapod.net/root )
had 5 failed jobs.

Job #252947 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/252947/raw )

Stage: tests
Name: test-py2-chg
Job #252944 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/252944/raw )

Stage: tests
Name: test-py2-rust
Job #252940 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/252940/raw )

Stage: tests
Name: test-py2
Job #252942 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/252942/raw )

Stage: tests
Name: test-py2-pure
Job #252936 ( 
https://foss.heptapod.net/mercurial/mercurial-devel/-/jobs/252936/raw )

Stage: tests
Name: checks-py2

-- 
You're receiving this email because of your account on foss.heptapod.net.



___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D11650: rhg: handle null changelog and manifest revisions

2021-10-12 Thread aalekseyev (Arseniy Alekseyev)
aalekseyev created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11650

AFFECTED FILES
  rust/hg-core/src/revlog/changelog.rs
  rust/hg-core/src/revlog/index.rs
  rust/hg-core/src/revlog/revlog.rs
  tests/test-empty-manifest-index.t

CHANGE DETAILS

diff --git a/tests/test-empty-manifest-index.t 
b/tests/test-empty-manifest-index.t
new file mode 100644
--- /dev/null
+++ b/tests/test-empty-manifest-index.t
@@ -0,0 +1,23 @@
+Create a repo such that the changelog entry refers to a null manifest node:
+
+  $ hg init a
+  $ cd a
+  $ hg log
+  $ touch x
+  $ hg add x
+  $ hg commit -m "init"
+  $ hg rm x
+  $ hg commit -q --amend
+
+  $ wc -c < .hg/store/00manifest.i
+  0
+
+Make sure that the manifest can be read (and is empty):
+
+  $ hg --config rhg.on-unsupported=abort files -r .
+  [1]
+
+Test a null changelog rev, too:
+
+  $ hg --config rhg.on-unsupported=abort files -r 

+  [1]
diff --git a/rust/hg-core/src/revlog/revlog.rs 
b/rust/hg-core/src/revlog/revlog.rs
--- a/rust/hg-core/src/revlog/revlog.rs
+++ b/rust/hg-core/src/revlog/revlog.rs
@@ -72,7 +72,7 @@
 let index_path = index_path.as_ref();
 let index_mmap = repo.store_vfs().mmap_open(_path)?;
 
-let version = get_version(_mmap);
+let version = get_version(_mmap)?;
 if version != 1 {
 // A proper new version should have had a repo/store requirement.
 return Err(HgError::corrupted("corrupted revlog"));
@@ -179,6 +179,9 @@
 /// snapshot to rebuild the final data.
 #[timed]
 pub fn get_rev_data(, rev: Revision) -> Result, RevlogError> {
+if rev == NULL_REVISION {
+return Ok(vec![]);
+};
 // Todo return -> Cow
 let mut entry = self.get_entry(rev)?;
 let mut delta_chain = vec![];
@@ -371,8 +374,16 @@
 }
 
 /// Format version of the revlog.
-pub fn get_version(index_bytes: &[u8]) -> u16 {
-BigEndian::read_u16(_bytes[2..=3])
+pub fn get_version(index_bytes: &[u8]) -> Result {
+if index_bytes.len() == 0 {
+return Ok(1);
+};
+if index_bytes.len() < 4 {
+return Err(HgError::corrupted(
+"corrupted revlog: can't read the index format header",
+));
+};
+Ok(BigEndian::read_u16(_bytes[2..=3]))
 }
 
 /// Calculate the hash of a revision given its data and its parents.
diff --git a/rust/hg-core/src/revlog/index.rs b/rust/hg-core/src/revlog/index.rs
--- a/rust/hg-core/src/revlog/index.rs
+++ b/rust/hg-core/src/revlog/index.rs
@@ -208,6 +208,9 @@
 
 /// Value of the inline flag.
 pub fn is_inline(index_bytes: &[u8]) -> bool {
+if index_bytes.len() < 4 {
+return true;
+}
 match _bytes[0..=1] {
 [0, 0] | [0, 2] => false,
 _ => true,
diff --git a/rust/hg-core/src/revlog/changelog.rs 
b/rust/hg-core/src/revlog/changelog.rs
--- a/rust/hg-core/src/revlog/changelog.rs
+++ b/rust/hg-core/src/revlog/changelog.rs
@@ -1,5 +1,6 @@
 use crate::errors::HgError;
 use crate::repo::Repo;
+use crate::revlog::node::NULL_NODE;
 use crate::revlog::revlog::{Revlog, RevlogError};
 use crate::revlog::Revision;
 use crate::revlog::{Node, NodePrefix};
@@ -58,10 +59,9 @@
 /// Return the node id of the `manifest` referenced by this `changelog`
 /// entry.
 pub fn manifest_node() -> Result {
-Node::from_hex_for_repo(
-self.lines()
-.next()
-.ok_or_else(|| HgError::corrupted("empty changelog entry"))?,
-)
+match self.lines().next() {
+None => Ok(NULL_NODE),
+Some(x) => Node::from_hex_for_repo(x),
+}
 }
 }



To: aalekseyev, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D11649: chistedit: move changeview() onto state class

2021-10-12 Thread martinvonz (Martin von Zweigbergk)
martinvonz created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11649

AFFECTED FILES
  hgext/histedit.py

CHANGE DETAILS

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1193,23 +1193,6 @@
 return self.conflicts
 
 
-#  EVENTS ===
-def changeview(state, delta, unit):
-"""Change the region of whatever is being viewed (a patch or the list of
-changesets). 'delta' is an amount (+/- 1) and 'unit' is 'page' or 
'line'."""
-mode, _ = state.mode
-if mode != MODE_PATCH:
-return
-mode_state = state.modes[mode]
-num_lines = len(mode_state[b'patchcontents'])
-page_height = state.page_height
-unit = page_height if unit == b'page' else 1
-num_pages = 1 + (num_lines - 1) // page_height
-max_offset = (num_pages - 1) * page_height
-newline = mode_state[b'line_offset'] + delta * unit
-mode_state[b'line_offset'] = max(0, min(max_offset, newline))
-
-
 def makecommands(rules):
 """Returns a list of commands consumable by histedit --commands based on
 our list of rules"""
@@ -1586,6 +1569,21 @@
 index -= 1
 self.change_action(pos, KEY_LIST[index % len(KEY_LIST)])
 
+def change_view(self, delta, unit):
+"""Change the region of whatever is being viewed (a patch or the list 
of
+changesets). 'delta' is an amount (+/- 1) and 'unit' is 'page' or 
'line'."""
+mode, _ = self.mode
+if mode != MODE_PATCH:
+return
+mode_state = self.modes[mode]
+num_lines = len(mode_state[b'patchcontents'])
+page_height = self.page_height
+unit = page_height if unit == b'page' else 1
+num_pages = 1 + (num_lines - 1) // page_height
+max_offset = (num_pages - 1) * page_height
+newline = mode_state[b'line_offset'] + delta * unit
+mode_state[b'line_offset'] = max(0, min(max_offset, newline))
+
 
 def _chisteditmain(repo, rules, stdscr):
 try:
@@ -1657,13 +1655,13 @@
 
 if e in (E_PAGEDOWN, E_PAGEUP, E_LINEDOWN, E_LINEUP):
 if e == E_PAGEDOWN:
-changeview(state, +1, b'page')
+state.change_view(+1, b'page')
 elif e == E_PAGEUP:
-changeview(state, -1, b'page')
+state.change_view(-1, b'page')
 elif e == E_LINEDOWN:
-changeview(state, +1, b'line')
+state.change_view(+1, b'line')
 elif e == E_LINEUP:
-changeview(state, -1, b'line')
+state.change_view(-1, b'line')
 
 # start rendering
 commitwin.erase()



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D11648: chistedit: move cycleaction() onto state class

2021-10-12 Thread martinvonz (Martin von Zweigbergk)
martinvonz created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11648

AFFECTED FILES
  hgext/histedit.py

CHANGE DETAILS

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1194,23 +1194,6 @@
 
 
 #  EVENTS ===
-def cycleaction(state, pos, next=False):
-"""Changes the action state the next or the previous action from
-the action list"""
-rules = state.rules
-assert 0 <= pos < len(rules)
-current = rules[pos].action
-
-assert current in KEY_LIST
-
-index = KEY_LIST.index(current)
-if next:
-index += 1
-else:
-index -= 1
-state.change_action(pos, KEY_LIST[index % len(KEY_LIST)])
-
-
 def changeview(state, delta, unit):
 """Change the region of whatever is being viewed (a patch or the list of
 changesets). 'delta' is an amount (+/- 1) and 'unit' is 'page' or 
'line'."""
@@ -1486,9 +1469,9 @@
 if selected is not None or action == b'move-up':
 self.swap(oldpos, newpos)
 elif action == b'next-action':
-cycleaction(self, oldpos, next=True)
+self.cycle_action(oldpos, next=True)
 elif action == b'prev-action':
-cycleaction(self, oldpos, next=False)
+self.cycle_action(oldpos, next=False)
 elif action == b'select':
 selected = oldpos if selected is None else None
 self.make_selection(selected)
@@ -1587,6 +1570,22 @@
 assert 0 <= pos < len(rules)
 rules[pos].action = action
 
+def cycle_action(self, pos, next=False):
+"""Changes the action state the next or the previous action from
+the action list"""
+rules = self.rules
+assert 0 <= pos < len(rules)
+current = rules[pos].action
+
+assert current in KEY_LIST
+
+index = KEY_LIST.index(current)
+if next:
+index += 1
+else:
+index -= 1
+self.change_action(pos, KEY_LIST[index % len(KEY_LIST)])
+
 
 def _chisteditmain(repo, rules, stdscr):
 try:



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D11647: chistedit: move changeaction() onto state class

2021-10-12 Thread martinvonz (Martin von Zweigbergk)
martinvonz created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11647

AFFECTED FILES
  hgext/histedit.py

CHANGE DETAILS

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1194,13 +1194,6 @@
 
 
 #  EVENTS ===
-def changeaction(state, pos, action):
-"""Change the action state on the given position to the new action"""
-rules = state.rules
-assert 0 <= pos < len(rules)
-rules[pos].action = action
-
-
 def cycleaction(state, pos, next=False):
 """Changes the action state the next or the previous action from
 the action list"""
@@ -1215,7 +1208,7 @@
 index += 1
 else:
 index -= 1
-changeaction(state, pos, KEY_LIST[index % len(KEY_LIST)])
+state.change_action(pos, KEY_LIST[index % len(KEY_LIST)])
 
 
 def changeview(state, delta, unit):
@@ -1505,7 +1498,7 @@
 if selected is not None:
 self.swap(oldpos, newrule.pos)
 elif action.startswith(b'action-'):
-changeaction(self, oldpos, action[7:])
+self.change_action(oldpos, action[7:])
 elif action == b'showpatch':
 self.change_mode(MODE_PATCH if curmode != MODE_PATCH else prevmode)
 elif action == b'help':
@@ -1588,6 +1581,12 @@
 if self.selected:
 self.make_selection(newpos)
 
+def change_action(self, pos, action):
+"""Change the action state on the given position to the new action"""
+rules = self.rules
+assert 0 <= pos < len(rules)
+rules[pos].action = action
+
 
 def _chisteditmain(repo, rules, stdscr):
 try:



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D11646: chistedit: move swap() onto state class

2021-10-12 Thread martinvonz (Martin von Zweigbergk)
martinvonz created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11646

AFFECTED FILES
  hgext/histedit.py

CHANGE DETAILS

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1194,29 +1194,6 @@
 
 
 #  EVENTS ===
-def swap(state, oldpos, newpos):
-"""Swap two positions and calculate necessary conflicts in
-O(|newpos-oldpos|) time"""
-
-rules = state.rules
-assert 0 <= oldpos < len(rules) and 0 <= newpos < len(rules)
-
-rules[oldpos], rules[newpos] = rules[newpos], rules[oldpos]
-
-# TODO: swap should not know about histeditrule's internals
-rules[newpos].pos = newpos
-rules[oldpos].pos = oldpos
-
-start = min(oldpos, newpos)
-end = max(oldpos, newpos)
-for r in pycompat.xrange(start, end + 1):
-rules[newpos].checkconflicts(rules[r])
-rules[oldpos].checkconflicts(rules[r])
-
-if state.selected:
-state.make_selection(newpos)
-
-
 def changeaction(state, pos, action):
 """Change the action state on the given position to the new action"""
 rules = state.rules
@@ -1509,12 +1486,12 @@
 newpos = min(oldpos + 1, len(rules) - 1)
 self.move_cursor(oldpos, newpos)
 if selected is not None or action == b'move-down':
-swap(self, oldpos, newpos)
+self.swap(oldpos, newpos)
 elif action in (b'up', b'move-up'):
 newpos = max(0, oldpos - 1)
 self.move_cursor(oldpos, newpos)
 if selected is not None or action == b'move-up':
-swap(self, oldpos, newpos)
+self.swap(oldpos, newpos)
 elif action == b'next-action':
 cycleaction(self, oldpos, next=True)
 elif action == b'prev-action':
@@ -1526,7 +1503,7 @@
 newrule = next((r for r in rules if r.origpos == int(ch)))
 self.move_cursor(oldpos, newrule.pos)
 if selected is not None:
-swap(self, oldpos, newrule.pos)
+self.swap(oldpos, newrule.pos)
 elif action.startswith(b'action-'):
 changeaction(self, oldpos, action[7:])
 elif action == b'showpatch':
@@ -1589,6 +1566,28 @@
 def make_selection(self, pos):
 self.selected = pos
 
+def swap(self, oldpos, newpos):
+"""Swap two positions and calculate necessary conflicts in
+O(|newpos-oldpos|) time"""
+
+rules = self.rules
+assert 0 <= oldpos < len(rules) and 0 <= newpos < len(rules)
+
+rules[oldpos], rules[newpos] = rules[newpos], rules[oldpos]
+
+# TODO: swap should not know about histeditrule's internals
+rules[newpos].pos = newpos
+rules[oldpos].pos = oldpos
+
+start = min(oldpos, newpos)
+end = max(oldpos, newpos)
+for r in pycompat.xrange(start, end + 1):
+rules[newpos].checkconflicts(rules[r])
+rules[oldpos].checkconflicts(rules[r])
+
+if self.selected:
+self.make_selection(newpos)
+
 
 def _chisteditmain(repo, rules, stdscr):
 try:



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D11645: chistedit: move makeselection() onto state class

2021-10-12 Thread martinvonz (Martin von Zweigbergk)
martinvonz created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11645

AFFECTED FILES
  hgext/histedit.py

CHANGE DETAILS

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1194,10 +1194,6 @@
 
 
 #  EVENTS ===
-def makeselection(state, pos):
-state.selected = pos
-
-
 def swap(state, oldpos, newpos):
 """Swap two positions and calculate necessary conflicts in
 O(|newpos-oldpos|) time"""
@@ -1218,7 +1214,7 @@
 rules[oldpos].checkconflicts(rules[r])
 
 if state.selected:
-makeselection(state, newpos)
+state.make_selection(newpos)
 
 
 def changeaction(state, pos, action):
@@ -1525,7 +1521,7 @@
 cycleaction(self, oldpos, next=False)
 elif action == b'select':
 selected = oldpos if selected is None else None
-makeselection(self, selected)
+self.make_selection(selected)
 elif action == b'goto' and int(ch) < len(rules) and len(rules) <= 10:
 newrule = next((r for r in rules if r.origpos == int(ch)))
 self.move_cursor(oldpos, newrule.pos)
@@ -1590,6 +1586,9 @@
 if mode == MODE_PATCH:
 self.modes[MODE_PATCH][b'patchcontents'] = self.patch_contents()
 
+def make_selection(self, pos):
+self.selected = pos
+
 
 def _chisteditmain(repo, rules, stdscr):
 try:



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D11644: chistedit: move changemode() onto state class

2021-10-12 Thread martinvonz (Martin von Zweigbergk)
martinvonz created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11644

AFFECTED FILES
  hgext/histedit.py

CHANGE DETAILS

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1194,13 +1194,6 @@
 
 
 #  EVENTS ===
-def changemode(state, mode):
-curmode, _ = state.mode
-state.mode = (mode, curmode)
-if mode == MODE_PATCH:
-state.modes[MODE_PATCH][b'patchcontents'] = state.patch_contents()
-
-
 def makeselection(state, pos):
 state.selected = pos
 
@@ -1541,9 +1534,9 @@
 elif action.startswith(b'action-'):
 changeaction(self, oldpos, action[7:])
 elif action == b'showpatch':
-changemode(self, MODE_PATCH if curmode != MODE_PATCH else prevmode)
+self.change_mode(MODE_PATCH if curmode != MODE_PATCH else prevmode)
 elif action == b'help':
-changemode(self, MODE_HELP if curmode != MODE_HELP else prevmode)
+self.change_mode(MODE_HELP if curmode != MODE_HELP else prevmode)
 elif action == b'quit':
 return E_QUIT
 elif action == b'histedit':
@@ -1591,6 +1584,12 @@
 # Reset the patch view region to the top of the new patch.
 self.modes[MODE_PATCH][b'line_offset'] = 0
 
+def change_mode(self, mode):
+curmode, _ = self.mode
+self.mode = (mode, curmode)
+if mode == MODE_PATCH:
+self.modes[MODE_PATCH][b'patchcontents'] = self.patch_contents()
+
 
 def _chisteditmain(repo, rules, stdscr):
 try:
@@ -1633,7 +1632,7 @@
 while True:
 oldmode, unused = state.mode
 if oldmode == MODE_INIT:
-changemode(state, MODE_RULES)
+state.change_mode(MODE_RULES)
 e = state.event(ch)
 
 if e == E_QUIT:



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D11643: chistedit: move movecursor() onto state class

2021-10-12 Thread martinvonz (Martin von Zweigbergk)
martinvonz created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11643

AFFECTED FILES
  hgext/histedit.py

CHANGE DETAILS

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1194,26 +1194,6 @@
 
 
 #  EVENTS ===
-def movecursor(state, oldpos, newpos):
-"""Change the rule/changeset that the cursor is pointing to, regardless of
-current mode (you can switch between patches from the view patch 
window)."""
-state.pos = newpos
-
-mode, _ = state.mode
-if mode == MODE_RULES:
-# Scroll through the list by updating the view for MODE_RULES, so that
-# even if we are not currently viewing the rules, switching back will
-# result in the cursor's rule being visible.
-modestate = state.modes[MODE_RULES]
-if newpos < modestate[b'line_offset']:
-modestate[b'line_offset'] = newpos
-elif newpos > modestate[b'line_offset'] + state.page_height - 1:
-modestate[b'line_offset'] = newpos - state.page_height + 1
-
-# Reset the patch view region to the top of the new patch.
-state.modes[MODE_PATCH][b'line_offset'] = 0
-
-
 def changemode(state, mode):
 curmode, _ = state.mode
 state.mode = (mode, curmode)
@@ -1538,12 +1518,12 @@
 return
 if action in (b'down', b'move-down'):
 newpos = min(oldpos + 1, len(rules) - 1)
-movecursor(self, oldpos, newpos)
+self.move_cursor(oldpos, newpos)
 if selected is not None or action == b'move-down':
 swap(self, oldpos, newpos)
 elif action in (b'up', b'move-up'):
 newpos = max(0, oldpos - 1)
-movecursor(self, oldpos, newpos)
+self.move_cursor(oldpos, newpos)
 if selected is not None or action == b'move-up':
 swap(self, oldpos, newpos)
 elif action == b'next-action':
@@ -1555,7 +1535,7 @@
 makeselection(self, selected)
 elif action == b'goto' and int(ch) < len(rules) and len(rules) <= 10:
 newrule = next((r for r in rules if r.origpos == int(ch)))
-movecursor(self, oldpos, newrule.pos)
+self.move_cursor(oldpos, newrule.pos)
 if selected is not None:
 swap(self, oldpos, newrule.pos)
 elif action.startswith(b'action-'):
@@ -1592,6 +1572,25 @@
 displayer.close()
 return displayer.hunk[rule.ctx.rev()].splitlines()
 
+def move_cursor(self, oldpos, newpos):
+"""Change the rule/changeset that the cursor is pointing to, 
regardless of
+current mode (you can switch between patches from the view patch 
window)."""
+self.pos = newpos
+
+mode, _ = self.mode
+if mode == MODE_RULES:
+# Scroll through the list by updating the view for MODE_RULES, so 
that
+# even if we are not currently viewing the rules, switching back 
will
+# result in the cursor's rule being visible.
+modestate = self.modes[MODE_RULES]
+if newpos < modestate[b'line_offset']:
+modestate[b'line_offset'] = newpos
+elif newpos > modestate[b'line_offset'] + self.page_height - 1:
+modestate[b'line_offset'] = newpos - self.page_height + 1
+
+# Reset the patch view region to the top of the new patch.
+self.modes[MODE_PATCH][b'line_offset'] = 0
+
 
 def _chisteditmain(repo, rules, stdscr):
 try:
@@ -1652,7 +1651,7 @@
 if curmode != oldmode:
 state.page_height = sizes[b'main'][0]
 # Adjust the view to fit the current screen size.
-movecursor(state, state.pos, state.pos)
+state.move_cursor(state.pos, state.pos)
 
 # Pack the windows against the top, each pane spread across the
 # full width of the screen.



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D11642: chistedit: move patchcontents() onto state class

2021-10-12 Thread martinvonz (Martin von Zweigbergk)
martinvonz created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11642

AFFECTED FILES
  hgext/histedit.py

CHANGE DETAILS

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1218,7 +1218,7 @@
 curmode, _ = state.mode
 state.mode = (mode, curmode)
 if mode == MODE_PATCH:
-state.modes[MODE_PATCH][b'patchcontents'] = patchcontents(state)
+state.modes[MODE_PATCH][b'patchcontents'] = state.patch_contents()
 
 
 def makeselection(state, pos):
@@ -1325,19 +1325,6 @@
 return line[: n - 2] + b' >'
 
 
-def patchcontents(state):
-repo = state.repo
-rule = state.rules[state.pos]
-displayer = logcmdutil.changesetdisplayer(
-repo.ui, repo, {b"patch": True, b"template": b"status"}, buffered=True
-)
-overrides = {(b'ui', b'verbose'): True}
-with repo.ui.configoverride(overrides, source=b'histedit'):
-displayer.show(rule.ctx)
-displayer.close()
-return displayer.hunk[rule.ctx.rev()].splitlines()
-
-
 class _chistedit_state(object):
 def __init__(
 self,
@@ -1590,6 +1577,21 @@
 elif action == b'line-up':
 return E_LINEUP
 
+def patch_contents(self):
+repo = self.repo
+rule = self.rules[self.pos]
+displayer = logcmdutil.changesetdisplayer(
+repo.ui,
+repo,
+{b"patch": True, b"template": b"status"},
+buffered=True,
+)
+overrides = {(b'ui', b'verbose'): True}
+with repo.ui.configoverride(overrides, source=b'histedit'):
+displayer.show(rule.ctx)
+displayer.close()
+return displayer.hunk[rule.ctx.rev()].splitlines()
+
 
 def _chisteditmain(repo, rules, stdscr):
 try:



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D11641: chistedit: move event() onto state class

2021-10-12 Thread martinvonz (Martin von Zweigbergk)
martinvonz created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11641

AFFECTED FILES
  hgext/histedit.py

CHANGE DETAILS

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1288,71 +1288,6 @@
 mode_state[b'line_offset'] = max(0, min(max_offset, newline))
 
 
-def event(state, ch):
-"""Change state based on the current character input
-
-This takes the current state and based on the current character input from
-the user we change the state.
-"""
-selected = state.selected
-oldpos = state.pos
-rules = state.rules
-
-if ch in (curses.KEY_RESIZE, b"KEY_RESIZE"):
-return E_RESIZE
-
-lookup_ch = ch
-if ch is not None and b'0' <= ch <= b'9':
-lookup_ch = b'0'
-
-curmode, prevmode = state.mode
-action = KEYTABLE[curmode].get(
-lookup_ch, KEYTABLE[b'global'].get(lookup_ch)
-)
-if action is None:
-return
-if action in (b'down', b'move-down'):
-newpos = min(oldpos + 1, len(rules) - 1)
-movecursor(state, oldpos, newpos)
-if selected is not None or action == b'move-down':
-swap(state, oldpos, newpos)
-elif action in (b'up', b'move-up'):
-newpos = max(0, oldpos - 1)
-movecursor(state, oldpos, newpos)
-if selected is not None or action == b'move-up':
-swap(state, oldpos, newpos)
-elif action == b'next-action':
-cycleaction(state, oldpos, next=True)
-elif action == b'prev-action':
-cycleaction(state, oldpos, next=False)
-elif action == b'select':
-selected = oldpos if selected is None else None
-makeselection(state, selected)
-elif action == b'goto' and int(ch) < len(rules) and len(rules) <= 10:
-newrule = next((r for r in rules if r.origpos == int(ch)))
-movecursor(state, oldpos, newrule.pos)
-if selected is not None:
-swap(state, oldpos, newrule.pos)
-elif action.startswith(b'action-'):
-changeaction(state, oldpos, action[7:])
-elif action == b'showpatch':
-changemode(state, MODE_PATCH if curmode != MODE_PATCH else prevmode)
-elif action == b'help':
-changemode(state, MODE_HELP if curmode != MODE_HELP else prevmode)
-elif action == b'quit':
-return E_QUIT
-elif action == b'histedit':
-return E_HISTEDIT
-elif action == b'page-down':
-return E_PAGEDOWN
-elif action == b'page-up':
-return E_PAGEUP
-elif action == b'line-down':
-return E_LINEDOWN
-elif action == b'line-up':
-return E_LINEUP
-
-
 def makecommands(rules):
 """Returns a list of commands consumable by histedit --commands based on
 our list of rules"""
@@ -1591,6 +1526,70 @@
 content = self.modes[MODE_PATCH][b'patchcontents']
 self.render_string(win, content[start:], diffcolors=True)
 
+def event(self, ch):
+"""Change state based on the current character input
+
+This takes the current state and based on the current character input 
from
+the user we change the state.
+"""
+selected = self.selected
+oldpos = self.pos
+rules = self.rules
+
+if ch in (curses.KEY_RESIZE, b"KEY_RESIZE"):
+return E_RESIZE
+
+lookup_ch = ch
+if ch is not None and b'0' <= ch <= b'9':
+lookup_ch = b'0'
+
+curmode, prevmode = self.mode
+action = KEYTABLE[curmode].get(
+lookup_ch, KEYTABLE[b'global'].get(lookup_ch)
+)
+if action is None:
+return
+if action in (b'down', b'move-down'):
+newpos = min(oldpos + 1, len(rules) - 1)
+movecursor(self, oldpos, newpos)
+if selected is not None or action == b'move-down':
+swap(self, oldpos, newpos)
+elif action in (b'up', b'move-up'):
+newpos = max(0, oldpos - 1)
+movecursor(self, oldpos, newpos)
+if selected is not None or action == b'move-up':
+swap(self, oldpos, newpos)
+elif action == b'next-action':
+cycleaction(self, oldpos, next=True)
+elif action == b'prev-action':
+cycleaction(self, oldpos, next=False)
+elif action == b'select':
+selected = oldpos if selected is None else None
+makeselection(self, selected)
+elif action == b'goto' and int(ch) < len(rules) and len(rules) <= 10:
+newrule = next((r for r in rules if r.origpos == int(ch)))
+movecursor(self, oldpos, newrule.pos)
+if selected is not None:
+swap(self, oldpos, newrule.pos)
+elif action.startswith(b'action-'):
+changeaction(self, oldpos, 

D11640: chistedit: move renderpatch() and dependencies onto state class

2021-10-12 Thread martinvonz (Martin von Zweigbergk)
martinvonz created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11640

AFFECTED FILES
  hgext/histedit.py

CHANGE DETAILS

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1564,6 +1564,33 @@
 
 rulesscr.noutrefresh()
 
+def render_string(self, win, output, diffcolors=False):
+maxy, maxx = win.getmaxyx()
+length = min(maxy - 1, len(output))
+for y in range(0, length):
+line = output[y]
+if diffcolors:
+if line and line[0] == b'+':
+win.addstr(
+y, 0, line, curses.color_pair(COLOR_DIFF_ADD_LINE)
+)
+elif line and line[0] == b'-':
+win.addstr(
+y, 0, line, curses.color_pair(COLOR_DIFF_DEL_LINE)
+)
+elif line.startswith(b'@@ '):
+win.addstr(y, 0, line, 
curses.color_pair(COLOR_DIFF_OFFSET))
+else:
+win.addstr(y, 0, line)
+else:
+win.addstr(y, 0, line)
+win.noutrefresh()
+
+def render_patch(self, win):
+start = self.modes[MODE_PATCH][b'line_offset']
+content = self.modes[MODE_PATCH][b'patchcontents']
+self.render_string(win, content[start:], diffcolors=True)
+
 
 def _chisteditmain(repo, rules, stdscr):
 try:
@@ -1592,33 +1619,6 @@
 except curses.error:
 pass
 
-def renderstring(win, state, output, diffcolors=False):
-maxy, maxx = win.getmaxyx()
-length = min(maxy - 1, len(output))
-for y in range(0, length):
-line = output[y]
-if diffcolors:
-if line and line[0] == b'+':
-win.addstr(
-y, 0, line, curses.color_pair(COLOR_DIFF_ADD_LINE)
-)
-elif line and line[0] == b'-':
-win.addstr(
-y, 0, line, curses.color_pair(COLOR_DIFF_DEL_LINE)
-)
-elif line.startswith(b'@@ '):
-win.addstr(y, 0, line, 
curses.color_pair(COLOR_DIFF_OFFSET))
-else:
-win.addstr(y, 0, line)
-else:
-win.addstr(y, 0, line)
-win.noutrefresh()
-
-def renderpatch(win, state):
-start = state.modes[MODE_PATCH][b'line_offset']
-content = state.modes[MODE_PATCH][b'patchcontents']
-renderstring(win, state, content[start:], diffcolors=True)
-
 def drawvertwin(size, y, x):
 win = curses.newwin(size[0], size[1], y, x)
 y += size[0]
@@ -1675,9 +1675,9 @@
 helpwin.erase()
 mainwin.erase()
 if curmode == MODE_PATCH:
-renderpatch(mainwin, state)
+state.render_patch(mainwin)
 elif curmode == MODE_HELP:
-renderstring(mainwin, state, __doc__.strip().splitlines())
+state.render_string(mainwin, __doc__.strip().splitlines())
 else:
 state.render_rules(mainwin)
 state.render_commit(commitwin)



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D11639: chistedit: move renderrules() onto state class

2021-10-12 Thread martinvonz (Martin von Zweigbergk)
martinvonz created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11639

AFFECTED FILES
  hgext/histedit.py

CHANGE DETAILS

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1517,39 +1517,11 @@
 b'main': (mainlen, maxx),
 }
 
-
-def _chisteditmain(repo, rules, stdscr):
-try:
-curses.use_default_colors()
-except curses.error:
-pass
-
-# initialize color pattern
-curses.init_pair(COLOR_HELP, curses.COLOR_WHITE, curses.COLOR_BLUE)
-curses.init_pair(COLOR_SELECTED, curses.COLOR_BLACK, curses.COLOR_WHITE)
-curses.init_pair(COLOR_WARN, curses.COLOR_BLACK, curses.COLOR_YELLOW)
-curses.init_pair(COLOR_OK, curses.COLOR_BLACK, curses.COLOR_GREEN)
-curses.init_pair(COLOR_CURRENT, curses.COLOR_WHITE, curses.COLOR_MAGENTA)
-curses.init_pair(COLOR_DIFF_ADD_LINE, curses.COLOR_GREEN, -1)
-curses.init_pair(COLOR_DIFF_DEL_LINE, curses.COLOR_RED, -1)
-curses.init_pair(COLOR_DIFF_OFFSET, curses.COLOR_MAGENTA, -1)
-curses.init_pair(COLOR_ROLL, curses.COLOR_RED, -1)
-curses.init_pair(
-COLOR_ROLL_CURRENT, curses.COLOR_BLACK, curses.COLOR_MAGENTA
-)
-curses.init_pair(COLOR_ROLL_SELECTED, curses.COLOR_RED, curses.COLOR_WHITE)
-
-# don't display the cursor
-try:
-curses.curs_set(0)
-except curses.error:
-pass
-
-def renderrules(rulesscr, state):
-rules = state.rules
-pos = state.pos
-selected = state.selected
-start = state.modes[MODE_RULES][b'line_offset']
+def render_rules(self, rulesscr):
+rules = self.rules
+pos = self.pos
+selected = self.selected
+start = self.modes[MODE_RULES][b'line_offset']
 
 conflicts = [r.ctx for r in rules if r.conflicts]
 if len(conflicts) > 0:
@@ -1559,7 +1531,7 @@
 addln(rulesscr, -1, 0, line, curses.color_pair(COLOR_WARN))
 
 for y, rule in enumerate(rules[start:]):
-if y >= state.page_height:
+if y >= self.page_height:
 break
 if len(rule.conflicts) > 0:
 rulesscr.addstr(y, 0, b" ", curses.color_pair(COLOR_WARN))
@@ -1592,6 +1564,34 @@
 
 rulesscr.noutrefresh()
 
+
+def _chisteditmain(repo, rules, stdscr):
+try:
+curses.use_default_colors()
+except curses.error:
+pass
+
+# initialize color pattern
+curses.init_pair(COLOR_HELP, curses.COLOR_WHITE, curses.COLOR_BLUE)
+curses.init_pair(COLOR_SELECTED, curses.COLOR_BLACK, curses.COLOR_WHITE)
+curses.init_pair(COLOR_WARN, curses.COLOR_BLACK, curses.COLOR_YELLOW)
+curses.init_pair(COLOR_OK, curses.COLOR_BLACK, curses.COLOR_GREEN)
+curses.init_pair(COLOR_CURRENT, curses.COLOR_WHITE, curses.COLOR_MAGENTA)
+curses.init_pair(COLOR_DIFF_ADD_LINE, curses.COLOR_GREEN, -1)
+curses.init_pair(COLOR_DIFF_DEL_LINE, curses.COLOR_RED, -1)
+curses.init_pair(COLOR_DIFF_OFFSET, curses.COLOR_MAGENTA, -1)
+curses.init_pair(COLOR_ROLL, curses.COLOR_RED, -1)
+curses.init_pair(
+COLOR_ROLL_CURRENT, curses.COLOR_BLACK, curses.COLOR_MAGENTA
+)
+curses.init_pair(COLOR_ROLL_SELECTED, curses.COLOR_RED, curses.COLOR_WHITE)
+
+# don't display the cursor
+try:
+curses.curs_set(0)
+except curses.error:
+pass
+
 def renderstring(win, state, output, diffcolors=False):
 maxy, maxx = win.getmaxyx()
 length = min(maxy - 1, len(output))
@@ -1679,7 +1679,7 @@
 elif curmode == MODE_HELP:
 renderstring(mainwin, state, __doc__.strip().splitlines())
 else:
-renderrules(mainwin, state)
+state.render_rules(mainwin)
 state.render_commit(commitwin)
 state.render_help(helpwin)
 curses.doupdate()



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D11638: chistedit: move layout() and dependencies onto state class

2021-10-12 Thread martinvonz (Martin von Zweigbergk)
martinvonz created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11638

AFFECTED FILES
  hgext/histedit.py

CHANGE DETAILS

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1408,9 +1408,11 @@
 self,
 repo,
 rules,
+stdscr,
 ):
 self.repo = repo
 self.rules = rules
+self.stdscr = stdscr
 self.pos = 0
 self.selected = None
 self.mode = (MODE_INIT, MODE_INIT)
@@ -1475,6 +1477,46 @@
 win.addstr(y, 1, conflictstr[:length])
 win.noutrefresh()
 
+def helplines(self):
+if self.mode[0] == MODE_PATCH:
+help = b"""\
+?: help, k/up: line up, j/down: line down, v: stop viewing patch
+pgup: prev page, space/pgdn: next page, c: commit, q: abort
+"""
+else:
+help = b"""\
+?: help, k/up: move up, j/down: move down, space: select, v: view patch
+d: drop, e: edit, f: fold, m: mess, p: pick, r: roll
+pgup/K: move patch up, pgdn/J: move patch down, c: commit, q: abort
+"""
+return help.splitlines()
+
+def render_help(self, win):
+maxy, maxx = win.getmaxyx()
+for y, line in enumerate(self.helplines()):
+if y >= maxy:
+break
+addln(win, y, 0, line, curses.color_pair(COLOR_HELP))
+win.noutrefresh()
+
+def layout(self):
+maxy, maxx = self.stdscr.getmaxyx()
+helplen = len(self.helplines())
+mainlen = maxy - helplen - 12
+if mainlen < 1:
+raise error.Abort(
+_(b"terminal dimensions %d by %d too small for curses 
histedit")
+% (maxy, maxx),
+hint=_(
+b"enlarge your terminal or use --config ui.interface=text"
+),
+)
+return {
+b'commit': (12, maxx),
+b'help': (helplen, maxx),
+b'main': (mainlen, maxx),
+}
+
 
 def _chisteditmain(repo, rules, stdscr):
 try:
@@ -1503,29 +1545,6 @@
 except curses.error:
 pass
 
-def helplines(mode):
-if mode == MODE_PATCH:
-help = b"""\
-?: help, k/up: line up, j/down: line down, v: stop viewing patch
-pgup: prev page, space/pgdn: next page, c: commit, q: abort
-"""
-else:
-help = b"""\
-?: help, k/up: move up, j/down: move down, space: select, v: view patch
-d: drop, e: edit, f: fold, m: mess, p: pick, r: roll
-pgup/K: move patch up, pgdn/J: move patch down, c: commit, q: abort
-"""
-return help.splitlines()
-
-def renderhelp(win, state):
-maxy, maxx = win.getmaxyx()
-mode, _ = state.mode
-for y, line in enumerate(helplines(mode)):
-if y >= maxy:
-break
-addln(win, y, 0, line, curses.color_pair(COLOR_HELP))
-win.noutrefresh()
-
 def renderrules(rulesscr, state):
 rules = state.rules
 pos = state.pos
@@ -1600,30 +1619,12 @@
 content = state.modes[MODE_PATCH][b'patchcontents']
 renderstring(win, state, content[start:], diffcolors=True)
 
-def layout(mode):
-maxy, maxx = stdscr.getmaxyx()
-helplen = len(helplines(mode))
-mainlen = maxy - helplen - 12
-if mainlen < 1:
-raise error.Abort(
-_(b"terminal dimensions %d by %d too small for curses 
histedit")
-% (maxy, maxx),
-hint=_(
-b"enlarge your terminal or use --config ui.interface=text"
-),
-)
-return {
-b'commit': (12, maxx),
-b'help': (helplen, maxx),
-b'main': (mainlen, maxx),
-}
-
 def drawvertwin(size, y, x):
 win = curses.newwin(size[0], size[1], y, x)
 y += size[0]
 return win, y, x
 
-state = _chistedit_state(repo, rules)
+state = _chistedit_state(repo, rules, stdscr)
 
 # eventloop
 ch = None
@@ -1645,8 +1646,8 @@
 if size != stdscr.getmaxyx():
 curses.resizeterm(*size)
 
+sizes = state.layout()
 curmode, unused = state.mode
-sizes = layout(curmode)
 if curmode != oldmode:
 state.page_height = sizes[b'main'][0]
 # Adjust the view to fit the current screen size.
@@ -1680,7 +1681,7 @@
 else:
 renderrules(mainwin, state)
 state.render_commit(commitwin)
-renderhelp(helpwin, state)
+state.render_help(helpwin)
 curses.doupdate()
 # done rendering
 ch = encoding.strtolocal(stdscr.getkey())



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

D11637: chistedit: move rendercommit() onto state class

2021-10-12 Thread martinvonz (Martin von Zweigbergk)
martinvonz created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11637

AFFECTED FILES
  hgext/histedit.py

CHANGE DETAILS

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1424,39 +1424,11 @@
 },
 }
 
-
-def _chisteditmain(repo, rules, stdscr):
-try:
-curses.use_default_colors()
-except curses.error:
-pass
-
-# initialize color pattern
-curses.init_pair(COLOR_HELP, curses.COLOR_WHITE, curses.COLOR_BLUE)
-curses.init_pair(COLOR_SELECTED, curses.COLOR_BLACK, curses.COLOR_WHITE)
-curses.init_pair(COLOR_WARN, curses.COLOR_BLACK, curses.COLOR_YELLOW)
-curses.init_pair(COLOR_OK, curses.COLOR_BLACK, curses.COLOR_GREEN)
-curses.init_pair(COLOR_CURRENT, curses.COLOR_WHITE, curses.COLOR_MAGENTA)
-curses.init_pair(COLOR_DIFF_ADD_LINE, curses.COLOR_GREEN, -1)
-curses.init_pair(COLOR_DIFF_DEL_LINE, curses.COLOR_RED, -1)
-curses.init_pair(COLOR_DIFF_OFFSET, curses.COLOR_MAGENTA, -1)
-curses.init_pair(COLOR_ROLL, curses.COLOR_RED, -1)
-curses.init_pair(
-COLOR_ROLL_CURRENT, curses.COLOR_BLACK, curses.COLOR_MAGENTA
-)
-curses.init_pair(COLOR_ROLL_SELECTED, curses.COLOR_RED, curses.COLOR_WHITE)
-
-# don't display the cursor
-try:
-curses.curs_set(0)
-except curses.error:
-pass
-
-def rendercommit(win, state):
+def render_commit(self, win):
 """Renders the commit window that shows the log of the current selected
 commit"""
-pos = state.pos
-rules = state.rules
+pos = self.pos
+rules = self.rules
 rule = rules[pos]
 
 ctx = rule.ctx
@@ -1471,7 +1443,7 @@
 line = b"user:  %s" % ctx.user()
 win.addstr(2, 1, line[:length])
 
-bms = repo.nodebookmarks(ctx.node())
+bms = self.repo.nodebookmarks(ctx.node())
 line = b"bookmark:  %s" % b' '.join(bms)
 win.addstr(3, 1, line[:length])
 
@@ -1503,6 +1475,34 @@
 win.addstr(y, 1, conflictstr[:length])
 win.noutrefresh()
 
+
+def _chisteditmain(repo, rules, stdscr):
+try:
+curses.use_default_colors()
+except curses.error:
+pass
+
+# initialize color pattern
+curses.init_pair(COLOR_HELP, curses.COLOR_WHITE, curses.COLOR_BLUE)
+curses.init_pair(COLOR_SELECTED, curses.COLOR_BLACK, curses.COLOR_WHITE)
+curses.init_pair(COLOR_WARN, curses.COLOR_BLACK, curses.COLOR_YELLOW)
+curses.init_pair(COLOR_OK, curses.COLOR_BLACK, curses.COLOR_GREEN)
+curses.init_pair(COLOR_CURRENT, curses.COLOR_WHITE, curses.COLOR_MAGENTA)
+curses.init_pair(COLOR_DIFF_ADD_LINE, curses.COLOR_GREEN, -1)
+curses.init_pair(COLOR_DIFF_DEL_LINE, curses.COLOR_RED, -1)
+curses.init_pair(COLOR_DIFF_OFFSET, curses.COLOR_MAGENTA, -1)
+curses.init_pair(COLOR_ROLL, curses.COLOR_RED, -1)
+curses.init_pair(
+COLOR_ROLL_CURRENT, curses.COLOR_BLACK, curses.COLOR_MAGENTA
+)
+curses.init_pair(COLOR_ROLL_SELECTED, curses.COLOR_RED, curses.COLOR_WHITE)
+
+# don't display the cursor
+try:
+curses.curs_set(0)
+except curses.error:
+pass
+
 def helplines(mode):
 if mode == MODE_PATCH:
 help = b"""\
@@ -1679,7 +1679,7 @@
 renderstring(mainwin, state, __doc__.strip().splitlines())
 else:
 renderrules(mainwin, state)
-rendercommit(commitwin, state)
+state.render_commit(commitwin)
 renderhelp(helpwin, state)
 curses.doupdate()
 # done rendering



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D11636: chistedit: move view state from a dict to a custom class

2021-10-12 Thread martinvonz (Martin von Zweigbergk)
martinvonz created this revision.
Herald added a reviewer: durin42.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11636

AFFECTED FILES
  hgext/histedit.py

CHANGE DETAILS

diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -1197,39 +1197,39 @@
 def movecursor(state, oldpos, newpos):
 """Change the rule/changeset that the cursor is pointing to, regardless of
 current mode (you can switch between patches from the view patch 
window)."""
-state[b'pos'] = newpos
-
-mode, _ = state[b'mode']
+state.pos = newpos
+
+mode, _ = state.mode
 if mode == MODE_RULES:
 # Scroll through the list by updating the view for MODE_RULES, so that
 # even if we are not currently viewing the rules, switching back will
 # result in the cursor's rule being visible.
-modestate = state[b'modes'][MODE_RULES]
+modestate = state.modes[MODE_RULES]
 if newpos < modestate[b'line_offset']:
 modestate[b'line_offset'] = newpos
-elif newpos > modestate[b'line_offset'] + state[b'page_height'] - 1:
-modestate[b'line_offset'] = newpos - state[b'page_height'] + 1
+elif newpos > modestate[b'line_offset'] + state.page_height - 1:
+modestate[b'line_offset'] = newpos - state.page_height + 1
 
 # Reset the patch view region to the top of the new patch.
-state[b'modes'][MODE_PATCH][b'line_offset'] = 0
+state.modes[MODE_PATCH][b'line_offset'] = 0
 
 
 def changemode(state, mode):
-curmode, _ = state[b'mode']
-state[b'mode'] = (mode, curmode)
+curmode, _ = state.mode
+state.mode = (mode, curmode)
 if mode == MODE_PATCH:
-state[b'modes'][MODE_PATCH][b'patchcontents'] = patchcontents(state)
+state.modes[MODE_PATCH][b'patchcontents'] = patchcontents(state)
 
 
 def makeselection(state, pos):
-state[b'selected'] = pos
+state.selected = pos
 
 
 def swap(state, oldpos, newpos):
 """Swap two positions and calculate necessary conflicts in
 O(|newpos-oldpos|) time"""
 
-rules = state[b'rules']
+rules = state.rules
 assert 0 <= oldpos < len(rules) and 0 <= newpos < len(rules)
 
 rules[oldpos], rules[newpos] = rules[newpos], rules[oldpos]
@@ -1244,13 +1244,13 @@
 rules[newpos].checkconflicts(rules[r])
 rules[oldpos].checkconflicts(rules[r])
 
-if state[b'selected']:
+if state.selected:
 makeselection(state, newpos)
 
 
 def changeaction(state, pos, action):
 """Change the action state on the given position to the new action"""
-rules = state[b'rules']
+rules = state.rules
 assert 0 <= pos < len(rules)
 rules[pos].action = action
 
@@ -1258,7 +1258,7 @@
 def cycleaction(state, pos, next=False):
 """Changes the action state the next or the previous action from
 the action list"""
-rules = state[b'rules']
+rules = state.rules
 assert 0 <= pos < len(rules)
 current = rules[pos].action
 
@@ -1275,12 +1275,12 @@
 def changeview(state, delta, unit):
 """Change the region of whatever is being viewed (a patch or the list of
 changesets). 'delta' is an amount (+/- 1) and 'unit' is 'page' or 
'line'."""
-mode, _ = state[b'mode']
+mode, _ = state.mode
 if mode != MODE_PATCH:
 return
-mode_state = state[b'modes'][mode]
+mode_state = state.modes[mode]
 num_lines = len(mode_state[b'patchcontents'])
-page_height = state[b'page_height']
+page_height = state.page_height
 unit = page_height if unit == b'page' else 1
 num_pages = 1 + (num_lines - 1) // page_height
 max_offset = (num_pages - 1) * page_height
@@ -1294,9 +1294,9 @@
 This takes the current state and based on the current character input from
 the user we change the state.
 """
-selected = state[b'selected']
-oldpos = state[b'pos']
-rules = state[b'rules']
+selected = state.selected
+oldpos = state.pos
+rules = state.rules
 
 if ch in (curses.KEY_RESIZE, b"KEY_RESIZE"):
 return E_RESIZE
@@ -1305,7 +1305,7 @@
 if ch is not None and b'0' <= ch <= b'9':
 lookup_ch = b'0'
 
-curmode, prevmode = state[b'mode']
+curmode, prevmode = state.mode
 action = KEYTABLE[curmode].get(
 lookup_ch, KEYTABLE[b'global'].get(lookup_ch)
 )
@@ -1391,8 +1391,8 @@
 
 
 def patchcontents(state):
-repo = state[b'repo']
-rule = state[b'rules'][state[b'pos']]
+repo = state.repo
+rule = state.rules[state.pos]
 displayer = logcmdutil.changesetdisplayer(
 repo.ui, repo, {b"patch": True, b"template": b"status"}, buffered=True
 )
@@ -1403,6 +1403,28 @@
 return displayer.hunk[rule.ctx.rev()].splitlines()
 
 
+class _chistedit_state(object):
+def __init__(
+self,
+repo,
+rules,
+):
+   

D11633: dirstate-v2: Truncate directory mtimes to 31 bits of seconds

2021-10-12 Thread SimonSapin
SimonSapin created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  … instead of 64 bits, while keeping the sub-second presision.
  This brings the size of one timestamp from 12 bytes to 8 bytes.
  
  31 bits is chosen instead of 32 because that’s already what happens for the
  mtime of files and symlinks, because dirstate-v1 uses negative i32 values as
  markers.
  
  Later we’ll add sub-second precision for file/symlink mtimes, making their
  dirstate-v2 representation the same as for directories.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11633

AFFECTED FILES
  mercurial/helptext/internals/dirstate-v2.txt
  rust/hg-core/src/dirstate/entry.rs
  rust/hg-core/src/dirstate_tree/dirstate_map.rs
  rust/hg-core/src/dirstate_tree/on_disk.rs
  rust/hg-core/src/dirstate_tree/status.rs

CHANGE DETAILS

diff --git a/rust/hg-core/src/dirstate_tree/status.rs 
b/rust/hg-core/src/dirstate_tree/status.rs
--- a/rust/hg-core/src/dirstate_tree/status.rs
+++ b/rust/hg-core/src/dirstate_tree/status.rs
@@ -1,4 +1,4 @@
-use crate::dirstate::entry::Timestamp;
+use crate::dirstate::entry::TruncatedTimestamp;
 use crate::dirstate::status::IgnoreFnType;
 use crate::dirstate_tree::dirstate_map::BorrowedPath;
 use crate::dirstate_tree::dirstate_map::ChildNodesRef;
@@ -126,7 +126,8 @@
 matcher: &'a (dyn Matcher + Sync),
 ignore_fn: IgnoreFnType<'a>,
 outcome: Mutex>,
-new_cachable_directories: Mutex, Timestamp)>>,
+new_cachable_directories:
+Mutex, TruncatedTimestamp)>>,
 outated_cached_directories: Mutex>>,
 
 /// Whether ignore files like `.hgignore` have changed since the previous
@@ -165,7 +166,7 @@
 dirstate_node: <'tree, 'on_disk>,
 ) -> Result<(), DirstateV2ParseError> {
 if self.ignore_patterns_have_changed == Some(true)
-&& dirstate_node.cached_directory_mtime().is_some()
+&& dirstate_node.cached_directory_mtime()?.is_some()
 {
 self.outated_cached_directories.lock().unwrap().push(
 dirstate_node
@@ -182,7 +183,7 @@
 fn can_skip_fs_readdir(
 ,
 directory_metadata: Option<::fs::Metadata>,
-cached_directory_mtime: Option,
+cached_directory_mtime: Option,
 ) -> bool {
 if !self.options.list_unknown && !self.options.list_ignored {
 // All states that we care about listing have corresponding
@@ -199,8 +200,9 @@
 // directory eligible for `read_dir` caching.
 if let Some(meta) = directory_metadata {
 if let Ok(current_mtime) = meta.modified() {
-let current_mtime = Timestamp::from(current_mtime);
-if current_mtime == cached_mtime {
+let truncated =
+TruncatedTimestamp::from(current_mtime);
+if truncated.very_likely_equal(_mtime) {
 // The mtime of that directory has not changed
 // since then, which means that the results of
 // `read_dir` should also be unchanged.
@@ -222,7 +224,7 @@
 directory_hg_path: <'tree, 'on_disk>,
 directory_fs_path: ,
 directory_metadata: Option<::fs::Metadata>,
-cached_directory_mtime: Option,
+cached_directory_mtime: Option,
 is_at_repo_root: bool,
 ) -> Result {
 if self.can_skip_fs_readdir(directory_metadata, cached_directory_mtime)
@@ -363,7 +365,7 @@
 hg_path,
 fs_path,
 Some(fs_metadata),
-dirstate_node.cached_directory_mtime(),
+dirstate_node.cached_directory_mtime()?,
 is_at_repo_root,
 )?;
 self.maybe_save_directory_mtime(
@@ -466,16 +468,22 @@
 //
 // We deem this scenario (unlike the previous one) to be
 // unlikely enough in practice.
-let timestamp = directory_mtime.into();
-let cached = dirstate_node.cached_directory_mtime();
-if cached != Some(timestamp) {
+let truncated = TruncatedTimestamp::from(directory_mtime);
+let is_up_to_date = if let Some(cached) =
+dirstate_node.cached_directory_mtime()?
+{
+cached.very_likely_equal()
+} else {
+false
+};
+if !is_up_to_date {
 let hg_path = dirstate_node
 .full_path_borrowed(self.dmap.on_disk)?
 .detach_from_tree();
 self.new_cachable_directories
 

D11635: dirstate-v2: Replace the 32-bit `mode` field with two bits

2021-10-12 Thread SimonSapin
SimonSapin created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  Previously we stored the entire value from `stat_result.st_mode`,
  like dirstate-v1 does. However only the executable permission
  and type of file (only symbolic links and normal files are supported)
  are relevant to Mecurial.
  
  So replace this field with two bits in the existing bitfield byte.
  For now the unused space is left as padding, as it will be used
  for something else soon.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11635

AFFECTED FILES
  mercurial/helptext/internals/dirstate-v2.txt
  rust/Cargo.lock
  rust/hg-core/Cargo.toml
  rust/hg-core/src/dirstate_tree/on_disk.rs
  rust/hg-cpython/Cargo.toml

CHANGE DETAILS

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
@@ -23,7 +23,7 @@
 [dependencies]
 crossbeam-channel = "0.4"
 hg-core = { path = "../hg-core"}
-libc = '*'
+libc = "0.2"
 log = "0.4.8"
 env_logger = "0.7.1"
 stable_deref_trait = "1.2.0"
diff --git a/rust/hg-core/src/dirstate_tree/on_disk.rs 
b/rust/hg-core/src/dirstate_tree/on_disk.rs
--- a/rust/hg-core/src/dirstate_tree/on_disk.rs
+++ b/rust/hg-core/src/dirstate_tree/on_disk.rs
@@ -107,13 +107,15 @@
 const P2_INFO = 1 << 2;
 const HAS_MODE_AND_SIZE = 1 << 3;
 const HAS_MTIME = 1 << 4;
+const MODE_EXEC_PERM = 1 << 5;
+const MODE_IS_SYMLINK = 1 << 7;
 }
 }
 
 #[derive(BytesCast, Copy, Clone, Debug)]
 #[repr(C)]
 struct Entry {
-mode: U32Be,
+_padding: U32Be,
 size: U32Be,
 mtime: U32Be,
 }
@@ -332,13 +334,27 @@
 )
 }
 
+fn synthesize_unix_mode() -> u32 {
+let file_type = if self.flags.contains(Flags::MODE_IS_SYMLINK) {
+libc::S_IFLNK
+} else {
+libc::S_IFREG
+};
+let permisions = if self.flags.contains(Flags::MODE_EXEC_PERM) {
+0o755
+} else {
+0o644
+};
+file_type | permisions
+}
+
 fn assume_entry() -> DirstateEntry {
 // TODO: convert through raw bits instead?
 let wdir_tracked = self.flags.contains(Flags::WDIR_TRACKED);
 let p1_tracked = self.flags.contains(Flags::P1_TRACKED);
 let p2_info = self.flags.contains(Flags::P2_INFO);
 let mode_size = if self.flags.contains(Flags::HAS_MODE_AND_SIZE) {
-Some((self.data.mode.into(), self.data.size.into()))
+Some((self.synthesize_unix_mode(), self.data.size.into()))
 } else {
 None
 };
@@ -400,13 +416,15 @@
 flags.set(Flags::WDIR_TRACKED, wdir_tracked);
 flags.set(Flags::P1_TRACKED, p1_tracked);
 flags.set(Flags::P2_INFO, p2_info);
-let (mode, size, mtime);
+let (size, mtime);
 if let Some((m, s)) = mode_size_opt {
-mode = m;
+let exec_perm = m & libc::S_IXUSR != 0;
+let is_symlink = m & libc::S_IFMT == libc::S_IFLNK;
+flags.set(Flags::MODE_EXEC_PERM, exec_perm);
+flags.set(Flags::MODE_IS_SYMLINK, is_symlink);
 size = s;
 flags.insert(Flags::HAS_MODE_AND_SIZE)
 } else {
-mode = 0;
 size = 0;
 }
 if let Some(m) = mtime_opt {
@@ -416,7 +434,7 @@
 mtime = 0;
 }
 let raw_entry = Entry {
-mode: mode.into(),
+_padding: 0.into(),
 size: size.into(),
 mtime: mtime.into(),
 };
@@ -600,7 +618,7 @@
 dirstate_map::NodeData::None => (
 Flags::empty(),
 Entry {
-mode: 0.into(),
+_padding: 0.into(),
 size: 0.into(),
 mtime: 0.into(),
 },
diff --git a/rust/hg-core/Cargo.toml b/rust/hg-core/Cargo.toml
--- a/rust/hg-core/Cargo.toml
+++ b/rust/hg-core/Cargo.toml
@@ -17,6 +17,7 @@
 im-rc = "15.0.*"
 itertools = "0.9"
 lazy_static = "1.4.0"
+libc = "0.2"
 rand = "0.7.3"
 rand_pcg = "0.2.1"
 rand_distr = "0.2.2"
diff --git a/rust/Cargo.lock b/rust/Cargo.lock
--- a/rust/Cargo.lock
+++ b/rust/Cargo.lock
@@ -1,5 +1,7 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
+version = 3
+
 [[package]]
 name = "adler"
 version = "0.2.3"
@@ -386,6 +388,7 @@
  "im-rc",
  "itertools",
  "lazy_static",
+ "libc",
  "log",
  "memmap2",
  "micro-timer",
diff --git a/mercurial/helptext/internals/dirstate-v2.txt 
b/mercurial/helptext/internals/dirstate-v2.txt
--- a/mercurial/helptext/internals/dirstate-v2.txt
+++ b/mercurial/helptext/internals/dirstate-v2.txt
@@ -380,6 +380,9 @@
 P2_INFO = 1 << 2
 HAS_MODE_AND_SIZE = 1 << 3
 

D11632: dirstate-v2: Separate Rust structs for Timestamp and PackedTimestamp

2021-10-12 Thread SimonSapin
SimonSapin created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  PackedTimestamp is now exclusively for dirstate-v2 serialization purpose.
  It contains unaligned big-endian integers. Timestamp is used everywhere else
  and contains native Rust integers.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11632

AFFECTED FILES
  rust/hg-core/src/dirstate/entry.rs
  rust/hg-core/src/dirstate_tree/dirstate_map.rs
  rust/hg-core/src/dirstate_tree/on_disk.rs
  rust/hg-core/src/dirstate_tree/status.rs

CHANGE DETAILS

diff --git a/rust/hg-core/src/dirstate_tree/status.rs 
b/rust/hg-core/src/dirstate_tree/status.rs
--- a/rust/hg-core/src/dirstate_tree/status.rs
+++ b/rust/hg-core/src/dirstate_tree/status.rs
@@ -1,3 +1,4 @@
+use crate::dirstate::entry::Timestamp;
 use crate::dirstate::status::IgnoreFnType;
 use crate::dirstate_tree::dirstate_map::BorrowedPath;
 use crate::dirstate_tree::dirstate_map::ChildNodesRef;
@@ -5,7 +6,6 @@
 use crate::dirstate_tree::dirstate_map::NodeData;
 use crate::dirstate_tree::dirstate_map::NodeRef;
 use crate::dirstate_tree::on_disk::DirstateV2ParseError;
-use crate::dirstate_tree::on_disk::Timestamp;
 use crate::matchers::get_ignore_function;
 use crate::matchers::Matcher;
 use crate::utils::files::get_bytes_from_os_string;
@@ -182,7 +182,7 @@
 fn can_skip_fs_readdir(
 ,
 directory_metadata: Option<::fs::Metadata>,
-cached_directory_mtime: Option<>,
+cached_directory_mtime: Option,
 ) -> bool {
 if !self.options.list_unknown && !self.options.list_ignored {
 // All states that we care about listing have corresponding
@@ -200,7 +200,7 @@
 if let Some(meta) = directory_metadata {
 if let Ok(current_mtime) = meta.modified() {
 let current_mtime = Timestamp::from(current_mtime);
-if current_mtime == *cached_mtime {
+if current_mtime == cached_mtime {
 // The mtime of that directory has not changed
 // since then, which means that the results of
 // `read_dir` should also be unchanged.
@@ -222,7 +222,7 @@
 directory_hg_path: <'tree, 'on_disk>,
 directory_fs_path: ,
 directory_metadata: Option<::fs::Metadata>,
-cached_directory_mtime: Option<>,
+cached_directory_mtime: Option,
 is_at_repo_root: bool,
 ) -> Result {
 if self.can_skip_fs_readdir(directory_metadata, cached_directory_mtime)
@@ -468,7 +468,7 @@
 // unlikely enough in practice.
 let timestamp = directory_mtime.into();
 let cached = dirstate_node.cached_directory_mtime();
-if cached != Some() {
+if cached != Some(timestamp) {
 let hg_path = dirstate_node
 .full_path_borrowed(self.dmap.on_disk)?
 .detach_from_tree();
diff --git a/rust/hg-core/src/dirstate_tree/on_disk.rs 
b/rust/hg-core/src/dirstate_tree/on_disk.rs
--- a/rust/hg-core/src/dirstate_tree/on_disk.rs
+++ b/rust/hg-core/src/dirstate_tree/on_disk.rs
@@ -2,6 +2,7 @@
 //!
 //! See `mercurial/helptext/internals/dirstate-v2.txt`
 
+use crate::dirstate::Timestamp;
 use crate::dirstate_tree::dirstate_map::{self, DirstateMap, NodeRef};
 use crate::dirstate_tree::path_with_basename::WithBasename;
 use crate::errors::HgError;
@@ -15,7 +16,6 @@
 use format_bytes::format_bytes;
 use std::borrow::Cow;
 use std::convert::{TryFrom, TryInto};
-use std::time::{SystemTime, UNIX_EPOCH};
 
 /// Added at the start of `.hg/dirstate` when the "v2" format is used.
 /// This a redundant sanity check more than an actual "magic number" since
@@ -119,9 +119,9 @@
 }
 
 /// Duration since the Unix epoch
-#[derive(BytesCast, Copy, Clone, PartialEq)]
+#[derive(BytesCast, Copy, Clone)]
 #[repr(C)]
-pub(super) struct Timestamp {
+struct PackedTimestamp {
 seconds: I64Be,
 
 /// In `0 .. 1_000_000_000`.
@@ -316,14 +316,14 @@
 ) -> Result {
 if self.has_entry() {
 Ok(dirstate_map::NodeData::Entry(self.assume_entry()))
-} else if let Some() = self.cached_directory_mtime() {
+} else if let Some(mtime) = self.cached_directory_mtime() {
 Ok(dirstate_map::NodeData::CachedDirectory { mtime })
 } else {
 Ok(dirstate_map::NodeData::None)
 }
 }
 
-pub(super) fn cached_directory_mtime() -> Option<> {
+pub(super) fn cached_directory_mtime() -> Option {
 if self.flags.contains(Flags::HAS_MTIME) && !self.has_entry() {
 Some(self.data.as_timestamp())
 } else {
@@ -423,58 +423,23 @@
 }
 
 fn from_timestamp(timestamp: Timestamp) -> Self {
+let packed = PackedTimestamp {
+   

D11634: dirstate-v2: Store unsigned integers inside DirstateEntry

2021-10-12 Thread SimonSapin
SimonSapin created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  The negative marker values are not used anymore.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11634

AFFECTED FILES
  rust/hg-core/src/dirstate/entry.rs
  rust/hg-core/src/dirstate_tree/on_disk.rs
  rust/hg-cpython/src/dirstate/item.rs

CHANGE DETAILS

diff --git a/rust/hg-cpython/src/dirstate/item.rs 
b/rust/hg-cpython/src/dirstate/item.rs
--- a/rust/hg-cpython/src/dirstate/item.rs
+++ b/rust/hg-cpython/src/dirstate/item.rs
@@ -21,7 +21,7 @@
 p2_info: bool = false,
 has_meaningful_data: bool = true,
 has_meaningful_mtime: bool = true,
-parentfiledata: Option<(i32, i32, i32)> = None,
+parentfiledata: Option<(u32, u32, u32)> = None,
 
 ) -> PyResult {
 let mut mode_size_opt = None;
@@ -145,9 +145,9 @@
 
 def set_clean(
 ,
-mode: i32,
-size: i32,
-mtime: i32,
+mode: u32,
+size: u32,
+mtime: u32,
 ) -> PyResult {
 self.update(py, |entry| entry.set_clean(mode, size, mtime));
 Ok(PyNone)
diff --git a/rust/hg-core/src/dirstate_tree/on_disk.rs 
b/rust/hg-core/src/dirstate_tree/on_disk.rs
--- a/rust/hg-core/src/dirstate_tree/on_disk.rs
+++ b/rust/hg-core/src/dirstate_tree/on_disk.rs
@@ -11,7 +11,7 @@
 use crate::DirstateError;
 use crate::DirstateParents;
 use bitflags::bitflags;
-use bytes_cast::unaligned::{I32Be, U16Be, U32Be};
+use bytes_cast::unaligned::{U16Be, U32Be};
 use bytes_cast::BytesCast;
 use format_bytes::format_bytes;
 use std::borrow::Cow;
@@ -113,9 +113,9 @@
 #[derive(BytesCast, Copy, Clone, Debug)]
 #[repr(C)]
 struct Entry {
-mode: I32Be,
-size: I32Be,
-mtime: I32Be,
+mode: U32Be,
+size: U32Be,
+mtime: U32Be,
 }
 
 /// Duration since the Unix epoch
diff --git a/rust/hg-core/src/dirstate/entry.rs 
b/rust/hg-core/src/dirstate/entry.rs
--- a/rust/hg-core/src/dirstate/entry.rs
+++ b/rust/hg-core/src/dirstate/entry.rs
@@ -18,8 +18,8 @@
 #[derive(Debug, PartialEq, Copy, Clone)]
 pub struct DirstateEntry {
 pub(crate) flags: Flags,
-mode_size: Option<(i32, i32)>,
-mtime: Option,
+mode_size: Option<(u32, u32)>,
+mtime: Option,
 }
 
 bitflags! {
@@ -153,9 +153,17 @@
 wdir_tracked: bool,
 p1_tracked: bool,
 p2_info: bool,
-mode_size: Option<(i32, i32)>,
-mtime: Option,
+mode_size: Option<(u32, u32)>,
+mtime: Option,
 ) -> Self {
+if let Some((mode, size)) = mode_size {
+// TODO: return an error for out of range values?
+assert!(mode & !RANGE_MASK_31BIT == 0);
+assert!(size & !RANGE_MASK_31BIT == 0);
+}
+if let Some(mtime) = mtime {
+assert!(mtime & !RANGE_MASK_31BIT == 0);
+}
 let mut flags = Flags::empty();
 flags.set(Flags::WDIR_TRACKED, wdir_tracked);
 flags.set(Flags::P1_TRACKED, p1_tracked);
@@ -189,12 +197,19 @@
 mtime: None,
 }
 } else if mtime == MTIME_UNSET {
+// TODO: return an error for negative values?
+let mode = u32::try_from(mode).unwrap();
+let size = u32::try_from(size).unwrap();
 Self {
 flags: Flags::WDIR_TRACKED | Flags::P1_TRACKED,
 mode_size: Some((mode, size)),
 mtime: None,
 }
 } else {
+// TODO: return an error for negative values?
+let mode = u32::try_from(mode).unwrap();
+let size = u32::try_from(size).unwrap();
+let mtime = u32::try_from(mtime).unwrap();
 Self {
 flags: Flags::WDIR_TRACKED | Flags::P1_TRACKED,
 mode_size: Some((mode, size)),
@@ -282,7 +297,7 @@
 /// Returns `(wdir_tracked, p1_tracked, p2_info, mode_size, mtime)`
 pub(crate) fn v2_data(
 ,
-) -> (bool, bool, bool, Option<(i32, i32)>, Option) {
+) -> (bool, bool, bool, Option<(u32, u32)>, Option) {
 if !self.any_tracked() {
 // TODO: return an Option instead?
 panic!("Accessing v1_state of an untracked DirstateEntry")
@@ -316,7 +331,7 @@
 
 fn v1_mode() -> i32 {
 if let Some((mode, _size)) = self.mode_size {
-mode
+i32::try_from(mode).unwrap()
 } else {
 0
 }
@@ -338,7 +353,7 @@
 } else if self.added() {
 SIZE_NON_NORMAL
 } else if let Some((_mode, size)) = self.mode_size {
-size
+i32::try_from(size).unwrap()
 } else {
 SIZE_NON_NORMAL
 }
@@ -355,8 +370,10 @@
 MTIME_UNSET
 } else if 

D11631: dirstate-v2: Only convert from SystemTime to Timestamp and not back

2021-10-12 Thread SimonSapin
SimonSapin created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  Converting from Timestamp back to SystemTime was only used for equality
  comparison, but this can also be done on Timestamp values.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11631

AFFECTED FILES
  rust/hg-core/src/dirstate_tree/on_disk.rs
  rust/hg-core/src/dirstate_tree/status.rs

CHANGE DETAILS

diff --git a/rust/hg-core/src/dirstate_tree/status.rs 
b/rust/hg-core/src/dirstate_tree/status.rs
--- a/rust/hg-core/src/dirstate_tree/status.rs
+++ b/rust/hg-core/src/dirstate_tree/status.rs
@@ -199,7 +199,8 @@
 // directory eligible for `read_dir` caching.
 if let Some(meta) = directory_metadata {
 if let Ok(current_mtime) = meta.modified() {
-if current_mtime == cached_mtime.into() {
+let current_mtime = Timestamp::from(current_mtime);
+if current_mtime == *cached_mtime {
 // The mtime of that directory has not changed
 // since then, which means that the results of
 // `read_dir` should also be unchanged.
diff --git a/rust/hg-core/src/dirstate_tree/on_disk.rs 
b/rust/hg-core/src/dirstate_tree/on_disk.rs
--- a/rust/hg-core/src/dirstate_tree/on_disk.rs
+++ b/rust/hg-core/src/dirstate_tree/on_disk.rs
@@ -15,7 +15,7 @@
 use format_bytes::format_bytes;
 use std::borrow::Cow;
 use std::convert::{TryFrom, TryInto};
-use std::time::{Duration, SystemTime, UNIX_EPOCH};
+use std::time::{SystemTime, UNIX_EPOCH};
 
 /// Added at the start of `.hg/dirstate` when the "v2" format is used.
 /// This a redundant sanity check more than an actual "magic number" since
@@ -462,18 +462,6 @@
 }
 }
 
-impl From<&'_ Timestamp> for SystemTime {
-fn from(timestamp: &'_ Timestamp) -> Self {
-let secs = timestamp.seconds.get();
-let nanos = timestamp.nanoseconds.get();
-if secs >= 0 {
-UNIX_EPOCH + Duration::new(secs as u64, nanos)
-} else {
-UNIX_EPOCH - Duration::new((-secs) as u64, nanos)
-}
-}
-}
-
 fn read_hg_path(
 on_disk: &[u8],
 slice: PathSlice,



To: SimonSapin, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D11630: rust: update the rust-cpython crate to 0.7.0

2021-10-12 Thread SimonSapin
SimonSapin created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  This notably brings support for Python 3.10, and includes the panic message
  when propagating a Rust panic as a Python exception.
  
  
https://github.com/dgrunwald/rust-cpython/blob/master/CHANGELOG.md#070---2021-10-09

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11630

AFFECTED FILES
  rust/Cargo.lock
  rust/hg-cpython/Cargo.toml

CHANGE DETAILS

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
@@ -21,13 +21,10 @@
 python3-bin = ["cpython/python3-sys"]
 
 [dependencies]
+cpython = { version = "0.7.0", default-features = false }
 crossbeam-channel = "0.4"
 hg-core = { path = "../hg-core"}
 libc = '*'
 log = "0.4.8"
 env_logger = "0.7.1"
 stable_deref_trait = "1.2.0"
-
-[dependencies.cpython]
-version = "0.6.0"
-default-features = false
diff --git a/rust/Cargo.lock b/rust/Cargo.lock
--- a/rust/Cargo.lock
+++ b/rust/Cargo.lock
@@ -1,5 +1,7 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
+version = 3
+
 [[package]]
 name = "adler"
 version = "0.2.3"
@@ -157,9 +159,9 @@
 
 [[package]]
 name = "cpython"
-version = "0.6.0"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index;
-checksum = "8094679a4e9bfc8035572162624bc800eda35b5f9eff2537b9cd9aacc3d9782e"
+checksum = "b7d46ba8ace7f3a1d204ac5060a706d0a68de6b42eafb6a586cc08bebcffe664"
 dependencies = [
  "libc",
  "num-traits",
@@ -652,9 +654,9 @@
 
 [[package]]
 name = "python27-sys"
-version = "0.6.0"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index;
-checksum = "5826ddbc5366eb0b0492040fdc25bf50bb49092c192bd45e80fb7a24dc6832ab"
+checksum = "94670354e264300dde81a5864cbb6bfc9d56ac3dcf3a278c32cb52f816f4dfd1"
 dependencies = [
  "libc",
  "regex",
@@ -662,9 +664,9 @@
 
 [[package]]
 name = "python3-sys"
-version = "0.6.0"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index;
-checksum = "b78af21b29594951a47fc3dac9b9eff0a3f077dec2f780ee943ae16a668f3b6a"
+checksum = "b18b32e64c103d5045f44644d7d65336f7a0521f6fde673240a9ecceb77e"
 dependencies = [
  "libc",
  "regex",



To: SimonSapin, #hg-reviewers
Cc: mercurial-patches, mercurial-devel
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


D11629: dirstate-v2: Change the representation of negative directory mtime

2021-10-12 Thread SimonSapin
SimonSapin created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  Change it from how I previously thought C’s `timespec` works
  to how it actually works.
  
  The previous behavior was also buggy for timestamps strictly before the
  epoch but less than one second away from it, because two’s complement
  does not distinguish negative zero from positive zero.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11629

AFFECTED FILES
  mercurial/helptext/internals/dirstate-v2.txt
  rust/hg-core/src/dirstate_tree/on_disk.rs

CHANGE DETAILS

diff --git a/rust/hg-core/src/dirstate_tree/on_disk.rs 
b/rust/hg-core/src/dirstate_tree/on_disk.rs
--- a/rust/hg-core/src/dirstate_tree/on_disk.rs
+++ b/rust/hg-core/src/dirstate_tree/on_disk.rs
@@ -126,8 +126,7 @@
 
 /// In `0 .. 1_000_000_000`.
 ///
-/// This timestamp is later or earlier than `(seconds, 0)` by this many
-/// nanoseconds, if `seconds` is non-negative or negative, respectively.
+/// This timestamp is after `(seconds, 0)` by this many nanoseconds.
 nanoseconds: U32Be,
 }
 
@@ -444,15 +443,33 @@
 }
 }
 
+const NSEC_PER_SEC: u32 = 1_000_000_000;
+
 impl From for Timestamp {
 fn from(system_time: SystemTime) -> Self {
+// On Unix, `SystemTime` is a wrapper for the `timespec` C struct:
+// 
https://www.gnu.org/software/libc/manual/html_node/Time-Types.html#index-struct-timespec
+// We want to effectively access its fields, but the Rust standard
+// library does not expose them. The best we can do is:
 let (secs, nanos) = match system_time.duration_since(UNIX_EPOCH) {
 Ok(duration) => {
 (duration.as_secs() as i64, duration.subsec_nanos())
 }
 Err(error) => {
+// `system_time` is before `UNIX_EPOCH`.
+// We need to undo this algorithm:
+// 
https://github.com/rust-lang/rust/blob/6bed1f0bc3cc50c10aab26d5f94b16a00776b8a5/library/std/src/sys/unix/time.rs#L40-L41
 let negative = error.duration();
-(-(negative.as_secs() as i64), negative.subsec_nanos())
+let negative_secs = negative.as_secs() as i64;
+let negative_nanos = negative.subsec_nanos();
+if negative_nanos == 0 {
+(-negative_secs, 0)
+} else {
+// For example if `system_time` was 4.3 seconds before
+// the Unix epoch we get a Duration that represents
+// `(-4, -0.3)` but we want `(-5, +0.7)`:
+(-1 - negative_secs, NSEC_PER_SEC - negative_nanos)
+}
 }
 };
 Timestamp {
@@ -466,10 +483,17 @@
 fn from(timestamp: &'_ Timestamp) -> Self {
 let secs = timestamp.seconds.get();
 let nanos = timestamp.nanoseconds.get();
-if secs >= 0 {
+if secs < 0 {
+let (s_to_subtract, ns_to_subtract) = if nanos == 0 {
+(-secs, 0)
+} else {
+// Example: `(-5, +0.7)` → `(-4, -0.3)`
+// See `impl From for Timestamp` above
+(1 - secs, NSEC_PER_SEC - nanos)
+};
+UNIX_EPOCH - Duration::new(s_to_subtract as u64, ns_to_subtract)
+} else {
 UNIX_EPOCH + Duration::new(secs as u64, nanos)
-} else {
-UNIX_EPOCH - Duration::new((-secs) as u64, nanos)
 }
 }
 }
diff --git a/mercurial/helptext/internals/dirstate-v2.txt 
b/mercurial/helptext/internals/dirstate-v2.txt
--- a/mercurial/helptext/internals/dirstate-v2.txt
+++ b/mercurial/helptext/internals/dirstate-v2.txt
@@ -443,20 +443,19 @@
 
   If an untracked node `HAS_MTIME` *set*,
   what follows is the modification time of a directory
-  represented with separated second and sub-second components
-  since the Unix epoch:
+  represented similarly to the C `timespec` struct:
 
   * Offset 31:
-The number of seconds as a signed (two’s complement) 64-bit integer.
+The number of seconds elapsed since the Unix epoch,
+as a signed (two’s complement) 64-bit integer.
 
   * Offset 39:
-The number of nanoseconds as 32-bit integer.
+The number of nanoseconds elapsed since
+the instant specified by the previous field alone,
+as 32-bit integer.
 Always greater than or equal to zero, and strictly less than a billion.
 Increasing this component makes the modification time
-go forward or backward in time dependening
-on the sign of the integral seconds components.
-(Note: this is buggy because there is no negative zero integer,
-but will be changed soon.)
+go forward in time regardless of the sign of the seconds component.
 
   The presence of a directory modification time means that at some point,
   this path in the working directory