Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking topics as remote refs #326

Open
riastradh opened this issue Jun 12, 2024 · 13 comments
Open

Tracking topics as remote refs #326

riastradh opened this issue Jun 12, 2024 · 13 comments

Comments

@riastradh
Copy link

Can git-cinnabar be convinced to track topics as remote refs, for repositories that use the hg topic extension?

For example, perhaps the most recent head of a topic T on a branch B could be exposed via refs/heads/branches/B/topics/T, even if git-cinnabar doesn't do anything with obsolete markers.

@glandium
Copy link
Owner

It already does... except git doesn't like it:

error: * Ignoring funny ref 'refs/remotes/origin/branches/default//foo/tip' locally

The problem is mercurial exposes topics as branches with // in their name to separate between the branch and the topic. Funnily enough, mercurial allows branch names with //, so you can create name conflicts with branches too.

$ hg branch default//foo
abort: a branch of the same name already exists

So I guess the only thing really needed is to translate branch//topic into something that git can be happy with... and that wouldn't conflict with something else.

@glandium
Copy link
Owner

(and obviously, since a branch can already be named with //, making it /topics/ wouldn't work, because a branch legitimately called foo//bar would become foo/topics/bar)

@riastradh
Copy link
Author

It looks like if you create a branch with // in its name, like foo//bar, Mercurial will treat it as if the branch were actually named foo//bar// when the topics extension is enabled.

Presumably you can tell which interpretation to use by the ?cmd=capabilities query?

@riastradh
Copy link
Author

Mercurial does, however, forbid topics with // in their names.

@glandium
Copy link
Owner

So... the weird thing is that branchmap apparently only exposes one topic. At least that's the behavior I'm seeing. There's a separate branchmaptns command that has all topics, but again it doesn't allow to distinguish between topics and branches with weird names. That branchmap exposes one topic seems like a bug, actually.

@riastradh
Copy link
Author

So... the weird thing is that branchmap apparently only exposes one topic. At least that's the behavior I'm seeing. There's a separate branchmaptns command that has all topics, but again it doesn't allow to distinguish between topics and branches with weird names. That branchmap exposes one topic seems like a bug, actually.

It looks like branchmap has some state in .hg/cache/branch2-served which causes its output to change. I don't know what's supposed to happen with it, but cursory review of the hg-evolve code suggests one should use branchmaptns for topics anyway if the topics-namespaces capability is advertised.

I tried creating two topics foo and bar on the default branch, and branches hello//world and quagga. branchmaptns returns:

default 754172d40ab5e418fc7ef50b5b9c9503631faa5e
default//foo 42302d303b803085afe6168d4226f1c7e3b4dcf0
default//bar d0ce871daa468dba3bd77008399c43fc54e80230
hello//world// f0db6f69a92c04823e07c08f9495be4f9ab35c66
quagga//// 640116bedba8ab57c6034a82cb6099efd48d61c1

So, empirically, with my small sample size, it looks like it is distinguishable: trailing // implies branch name (and hg topic '' does not create a topic with an empty name).

By code inspection, I see logic that appears to make this intentional in hg-evolve:

https://foss.heptapod.net/mercurial/evolve/-/blob/8275a04db4aec9faf15809ad251deeb59e42da49/hgext3rd/topic/common.py#L10-84

The documentation also suggests this is intentional:

  • branch// -> no topic

https://wiki.mercurial-scm.org/TopicPlan

@glandium
Copy link
Owner

So, apart from the refs problem, the thing about topic changesets is that, like for branch names, the topic name is hardcoded in the changeset itself, not as separate metadata. That data is, like for branch names, again, not represented in the git commit that would be created for it. As I understand it, once a topic is "promoted" to a non-draft state, a fresh changeset is created again without the topic name in it, which means that new changeset would map to the same git commit, which would conflict and break idempotency.

So, this is not, in fact, as simple as exposing the refs somehow.

@riastradh
Copy link
Author

As I understand it, once a topic is "promoted" to a non-draft state, a fresh changeset is created again without the topic name in it, [...]

I think this not accurate. The topic information remains encoded and the changeset identity does not change. Although hg log stops displaying the topic by default at that point, hg log --debug shows it is still there in an extra entry.

@riastradh
Copy link
Author

Filed a Mercurial bug report about the confusing cmd=branchmap behaviour: https://bz.mercurial-scm.org/show_bug.cgi?id=6890

But I would guess that doesn't need to get in the way here, since it looks like a topic-aware client should just use cmd=branchmaptns anyway.

@glandium
Copy link
Owner

As I understand it, once a topic is "promoted" to a non-draft state, a fresh changeset is created again without the topic name in it, [...]

I think this not accurate. The topic information remains encoded and the changeset identity does not change. Although hg log stops displaying the topic by default at that point, hg log --debug shows it is still there in an extra entry.

That's not what their wiki was saying :(

@riastradh
Copy link
Author

As I understand it, once a topic is "promoted" to a non-draft state, a fresh changeset is created again without the topic name in it, [...]

I think this not accurate. The topic information remains encoded and the changeset identity does not change. Although hg log stops displaying the topic by default at that point, hg log --debug shows it is still there in an extra entry.

That's not what their wiki was saying :(

Can you be more specific? Which part of the wiki?

@glandium
Copy link
Owner

https://wiki.mercurial-scm.org/TopicPlan
"This Topic data is primarily meant to categorize draft changeset and fade out when things become public"

@riastradh
Copy link
Author

https://wiki.mercurial-scm.org/TopicPlan
"This Topic data is primarily meant to categorize draft changeset and fade out when things become public"

I think that's consistent with hg log ceasing to display it, no? hg hides, rather than discards, historical records.

See also, e.g., Sec. 2.4.4 "Case 4: active topic, topic is closed" which shows the topic in a commit as faded, not deleted, or:

(Open ideas)

  • Topic could fade away when changesets become public (either archived or plain dropped)
    • A benefit of archiving them is that users can query for topics, eg you could say hg log -r topic(issue123) which would help

(Current implementation)
A topic is like a named branch, in that it is a label stored in a changeset's extra, but that topics just disappear when the change moves to public phase (the data still exists, it's just not shown.)

Nothing in the plan or the implementation that I see indicates altering changeset identity or discarding the topic-labelled changesets when topics are merged and published. (When changesets are rewritten via changeset evolution, yes, changeset identity changes and there are obsolescence markers published to map old changesets to new changesets. But, while it would be nice for git to take advantage of that, that's not the issue here.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants