view tests/test-pathconflicts-basic.t @ 49000:dd6b67d5c256 stable

rust: fix unsound `OwningDirstateMap` As per the previous patch, `OwningDirstateMap` is unsound. Self-referential structs are difficult to implement correctly in Rust since the compiler is free to move structs around as much as it wants to. They are also very rarely needed in practice, so the state-of-the-art on how they should be done within the Rust rules is still a bit new. The crate `ouroboros` is an attempt at providing a safe way (in the Rust sense) of declaring self-referential structs. It is getting a lot attention and was improved very quickly when soundness issues were found in the past: rather than relying on our own (limited) review circle, we might as well use the de-facto common crate to fix this problem. This will give us a much better chance of finding issues should any new ones be discovered as well as the benefit of fewer `unsafe` APIs of our own. I was starting to think about how I would present a safe API to the old struct but soon realized that the callback-based approach was already done in `ouroboros`, along with a lot more care towards refusing incorrect structs. In short: we don't return a mutable reference to the `DirstateMap` anymore, we expect users of its API to pass a `FnOnce` that takes the map as an argument. This allows our `OwningDirstateMap` to control the input and output lifetimes of the code that modifies it to prevent such issues. Changing to `ouroboros` meant changing every API with it, but it is relatively low churn in the end. It correctly identified the example buggy modification of `copy_map_insert` outlined in the previous patch as violating the borrow rules. Differential Revision: https://phab.mercurial-scm.org/D12429
author Raphaël Gomès <rgomes@octobus.net>
date Tue, 05 Apr 2022 10:55:28 +0200
parents dc00324e80f4
children
line wrap: on
line source

Path conflict checking is currently disabled by default because of issue5716.
Turn it on for this test.

  $ cat >> $HGRCPATH << EOF
  > [experimental]
  > merge.checkpathconflicts=True
  > EOF

  $ hg init repo
  $ cd repo
  $ echo base > base
  $ hg add base
  $ hg commit -m "base"
  $ hg bookmark -i base
  $ echo 1 > a
  $ hg add a
  $ hg commit -m "file"
  $ hg bookmark -i file
  $ echo 2 > a
  $ hg commit -m "file2"
  $ hg bookmark -i file2
  $ hg up -q 0
  $ mkdir a
  $ echo 2 > a/b
  $ hg add a/b
  $ hg commit -m "dir"
  created new head
  $ hg bookmark -i dir

Basic merge - local file conflicts with remote directory

  $ hg up -q file
  $ hg bookmark -i
  $ hg merge --verbose dir
  resolving manifests
  a: path conflict - a file or link has the same name as a directory
  the local file has been renamed to a~853701544ac3
  resolve manually then use 'hg resolve --mark a'
  moving a to a~853701544ac3
  getting a/b
  1 files updated, 0 files merged, 0 files removed, 1 files unresolved
  use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
  [1]
  $ hg update --clean .
  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
  $ rm a~853701544ac3

Basic update - local directory conflicts with remote file

  $ hg up -q 0
  $ mkdir a
  $ echo 3 > a/b
  $ hg up file
  a: untracked directory conflicts with file
  abort: untracked files in working directory differ from files in requested revision
  [20]
  $ hg up --clean file
  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
  (activating bookmark file)

Repo state is ok

  $ hg sum
  parent: 1:853701544ac3 
   file
  branch: default
  bookmarks: *file
  commit: (clean)
  update: 2 new changesets (update)
  phases: 4 draft

Basic update - untracked file conflicts with remote directory

  $ hg up -q 0
  $ echo untracked > a
  $ hg up --config merge.checkunknown=warn dir
  a: replacing untracked file
  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
  (activating bookmark dir)
  $ cat a.orig
  untracked
  $ rm -f a.orig

Basic clean update - local directory conflicts with changed remote file

  $ hg up -q file
  $ rm a
  $ mkdir a
  $ echo 4 > a/b
  $ hg up file2
  abort: *: *$TESTTMP/repo/a* (glob)
  [255]
  $ hg up --clean file2
  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
  (activating bookmark file2)

Repo state is ok

  $ hg sum
  parent: 2:f64e09fac717 
   file2
  branch: default
  bookmarks: *file2
  commit: (clean)
  update: 1 new changesets, 2 branch heads (merge)
  phases: 4 draft