Using the ACL extension of hg, I managed to prevent users to push on some branches (see [acl.deny.branches]) or some files (see [acl.deny], [acl.allow]).
However I would like to be able to mix both control. Here is an example:
we have two users, alice and bob
the repo is made of two files A and B
we have two branches, default and wip
alice should have RW access to both branches, on both A and B
bob should have RW access to A and B on the wip branch, but should have only
RW access to A on the default branch. bob must not be able to push a commit which modifies B on the default branch.
In this example, the access rights for bob are a mix of branch and file rules. Is it possible ?
Related
TLDR: I seem to have created a separate repository in a subfolder of my main project. How can I combine them?
I have a project folder, let's call it BOB. I cloned (hg clone) BOB to a new folder called BOB2. To add new features, I created a subfolder on BOB2 called BOB-newfeatures. I have been working on this BOB-newfeatures folder for a while, with many checkins.
Today I realized that somehow I created a separate repository for BOB-newfeatures (I hadn't changed anything on BOB2 main until today so I hadn't noticed that changes weren't being tracked). If I do hg status on BOB2, it doesn't know about changes in the subfolder and vice versa.
Is there a way to stitch these together? I know I could hg add all of the files in BOB-newfeatures to BOB but then I think I lose all of my checkin history.
OK, I reconstructed (I hope) your case, with your names, starting from
BOB2>hg log -T "{node|short}\tFiles: {join(files, ', ')}\n"
25a16a8fea5e Files: Sub/3.txt
bf3c6cacb4a4 Files: 1.txt, 2.txt
ff71a2b1bbe3 Files: 1.txt
and nested repo
BOB2\BOB-newfeatures>hg log -T "{node|short}\tFiles: {join(files, ', ')}\n"
acac7d413ed2 Files: f1.txt
15a1f9cacf25 Files: f2.txt
f3055921fa01 Files: f1.txt
As a additional confirmation of invisibility of BOB-newfeatures inside BOB2
BOB2>hg manifest
1.txt
2.txt
Sub/3.txt
Method of solving problem - using Convert extension with --filemap in inversed, compared to Wiki, direction: it's example transform subdir of repo into separate repository, I'll move repository-root into subfolder
map-file, prepared for conversion
rename . BOB-newfeatures
conversion
hg convert --filemap map z:\BOB2\BOB-newfeatures z:\BOB-newfeatures-conv
initializing destination z:\BOB-newfeatures-conv repository
scanning source...
sorting...
converting...
2 New feature started
1 Change 1
0 Change 2
Testing results
BOB-newfeatures-conv>hg log -T "{node|short}\tFiles: {join(files, ', ')}\n"
a3b2c462a3b9 Files: BOB-newfeatures/f1.txt
f5f1168cfe2f Files: BOB-newfeatures/f2.txt
da27a50a5cb6 Files: BOB-newfeatures/f1.txt
compare file-paths with log from nested repo, note different hashes for changesets
Next bad news: you can't just pull from BOB|BOB2 into converted repository missing parts easy
BOB-newfeatures-conv>hg pull ../BOB2
pulling from ../BOB2
searching for changes
abort: repository is unrelated
Even with --force (because repositories are really unrelated and doesn't share history) you'll get "dirty" combined repository (changes in root and in BOB-newfeatures/ are two separate lines of changes with own roots and tips)
BOB-newfeatures-conv>hg pull ../BOB2 -f
pulling from ../BOB2
searching for changes
warning: repository is unrelated
requesting all changes
adding changesets
adding manifests
adding file changes
added 3 changesets with 4 changes to 3 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
And at last step you have to re-link two histories into one common. In my case due to my actions (pulling to converted repository with pre-existing history of BOB-newfeatures) I had to link 0-1-2 revisions after 3-4-5 (historically earlier changes) and I don't know more elegant way to do it, than again convert (HG->HG) repository, with --splicemap this time
With log output
>hg log -T "{rev} {node}\n"
5 25a16a8fea5e5b4dac42a0a6b2c8e82890c220a3
4 bf3c6cacb4a4c22cb5720ddeab1ec5f8238a98c9
3 ff71a2b1bbe30a56c9dabc9a7ddb2bbccad840af
2 a3b2c462a3b917b3ba58daee3df2632875baee17
1 f5f1168cfe2f4b6c67d0af8a9259665ae2d40bd5
0 da27a50a5cb6246c03c6af7485ac7ffc33e62738
splicemap for rule "0 after 5" can be created (with format of oneliner "ChildHash ParentHash")
da27a50a5cb6246c03c6af7485ac7ffc33e62738 25a16a8fea5e5b4dac42a0a6b2c8e82890c220a3
and last conversion performed
>hg convert --splicemap z:\map z:\BOB-newfeatures-conv z:\BOB3
scanning source...
sorting...
converting...
5 Initial data
4 Changes
3 More changes
2 New feature started
spliced in 25a16a8fea5e5b4dac42a0a6b2c8e82890c220a3 as parents of da27a50a5cb6246c03c6af7485ac7ffc33e62738
1 Change 1
0 Change 2
with expected good results
You simply created a separate repository. As such you can pull from that repository like from any other. In this case, in your main repository in BOB2, you could do:
hg pull ./BOB-newfeatures
In order to avoid confusion, I'd first move BOB-newfeatures to the same directory level as BOB2 and pull then giving the new relative path ../BOB-newfeatures; but that's more for cosmetics and to keep your BOB2 repository clean; strictly speaking it should not be needed.
(Basically you used a feature of hg: you can create a new repo in any sub-path which will be an independent repo which knows nothing of the parent and vice versa. It's used for instance for libraries needed by the main repo but which you do not want to tie directly to your main; they then are found in the expected relative path and it's easy to operate on)
I have created a fork of repository A in Bitbucket, and named it repository B1.
Repository A has branch default, branch1 and branch2.
I created a copy of A on my machine that has only branches default and branch1, let's call it A2.
There was an error with my repository and I had to delete repository A (which is the parent for fork B), from Bitbucket, thus leaving fork B without a parent.
I uploaded repository A2 on Bitbucket with the name A.
My question is: How can I make repository A be the parent of fork B, so i can use Bitbucket's sync parent option?
ps: I use mercurial as source control.
Fork A1 call it B2.
Manually pull changesets from B into B2.
Check that B2 is now basically the same as B, but connected to A1 with your one click update.
Use B2 instead of B with optional renaming.
I'm afraid you cannot re-attach a parent to a fork, once the relationship is broken.
I have a distant repository called http://myrepo
I also have 3 projects with 3 distinct packages (1 in each) stored in D:/Projects/Project[ABC]/src/pack[ABC].
I would like to create a local repo in D:/Mercurial which will reference the packages pack[ABC] as subrepositories, which are to be pushed to my distant repo.
Finally, I would like to have my packages stored in my distant repo so you read http://myrepo/pack[ABC], and they should reflect the changes made in D:/Projects/Project[ABC]/src/pack[ABC].
I can't manage tu push my subrepositories to my distant one. How to set-up such a thing?
You should be able to configure your subrepos in your top repo's .hgsub as:
LocalPathA = http://server/A
LocalPathB = http://server/B
LocalPathC = http://server/C
Then, on Server, you will have to create empty repositories (with appropriate permissions) A, B, C
Your local repositories A,B,C will need their [paths] default=http://server/A, etc set up.
hgrc for the subs
[paths]
default = source repo
hgsub for the surrounding repo
protocol://servername//absolute/path/to/repo = relative/path/from/surrounding/repo/root
Before, when I was using perforce, I could work on multiple bugs at once as long as the code did not affect the same files, by having multiple change sets open at once.
Changeset 1:
A.txt
B.txt
C.txt
Changeset 2:
D.txt
E.txt
F.txt
I could submit changeset 2 to the repository without submitting changeset 1 (because it's still in progress)
Is this possible with Mercurial? other than doing each file as a separate commit?
You can always just do: hg commit D.txt E.txt F.txt to commit just those files which will leave A.txt, B.txt, and C.txt uncommited. Using the -I option to commit lets you do those with patterns if they're, for example, in a common directory: hg commit -I 'dir1/**'
You can have two separate branches (working copies) and make one change in and the other in the other. That's one way.
Another is to use Mercurial Queues. You can use qpush --move to change the order of changesets if they have no dependencies on one another, so you can then use qfinish to 'commit' the first changeset that's ready.
You don't actually hold changesets "open" in Mercurial.
Either you've committed your changes, or you haven't.
You can, however, have multiple files with uncommitted changes, and only commit a few of them. It is even possible to commit parts of files, chunks, instead of the whole file.
If I was to do what you're asking I would simply make another clone locally from my first one, and work on the two different fixes in two different working folders. Then I have all the freedom I need to combine the two (push/pull locally), push to the server, etc.
In Mercurial, cloning is a cheap operation when done locally. Just clone the repository for each thing you are working on. Push back to the main repository as each thing is ready:
hg clone http://project project
hg clone project project-bugfix // uses hardlinks and is inexpensive.
hg clone project project-feature
<edit bugfix and feature as needed>
But remember that the default push location is the project cloned from, so you'll either need to edit .hg\hgrc's default push path for the "project" clones, or make sure to hg push http://project from "project-bugfix" and "project-feature" when complete.
Even if your modifications touches the same file you can select what to include (hunk by hunk). You just have to activate the record extension (it's installed by not activated by default).
To activate the record extension, put this in the [extensions] section of your .hgrc:
[extensions]
hgext.record=
Then to commit, replace hg commit by hg record. Let's assume your example change sets with a G.txt file that have changes for both change sets. Commit with:
hg record D.txt E.txt F.txt G.txt
Answer questions, for example:
2 hunks, 6 lines changed
examine changes to 'D.txt'? [Ynsfdaq?] f # f for full file (help with ?)
... skipped file E and F
6 hunks, 35 lines changed
examine changes to 'G.txt'? [Ynsfdaq?] y
## ... (patch hunk here)
record change 6/16 to 'G.txt'? [Ynsfdaq?] y # y to include the hunk, n to skip
We have several shared libraries that exist as subrepos in a parent repo. If a person clones the parent repo, it looks something like:
/ParentRepo
---- .hg
---- .hgsub
---- .hgsubstate
---- SharedSub1
---- SharedSub2
---- SharedSub3
---- SharedSub4
---- ParentRepo.sln
.hgsub looks like this:
SharedSub1 = http://ourfogbugz.us.com/..../SharedSub1
SharedSub2 = http://ourfogbugz.us.com/..../SharedSub2
SharedSub3 = http://ourfogbugz.us.com/..../SharedSub3
SharedSub4 = http://ourfogbugz.us.com/..../SharedSub4
Each subrepo's hgrc looks something like this:
default = http://ourfogbugz.us.com/..../SharedSub1
Pretty standard stuff.
But!
How, using this setup, does a co-worker pull from another without using a central server as the intermediary? So co-worker A does 'hg serve', and B does 'hg pull http://coworkerA.us.com:8000'... but this will fail, as the hgsub file is still pointing at the central server, and thus B will only get changes from the central server, and not get any changes from A's subrepos that do not exist on the central server.
This is further complicated if the central server is down or unreachable. There is no way for people to pull from each other directly using subrepos!
How is pulling between co-workers done using subrepos? Editing the hgrc and hgsub files is out of the question, because you'd have to do it for each subrepo (we have around 20), and once for each co-worker!
I have also posted this question on the Kiln StackExchange to hit a broader audience: http://kiln.stackexchange.com/questions/1780/pulling-from-a-co-worker-when-using-subrepositories
You can (and generally should) use relative paths in your .hgsub entires. If those lines were:
SharedSub1 = ../SharedSub1
SharedSub2 = ../SharedSub2
SharedSub3 = ../SharedSub3
SharedSub4 = ../SharedSub4
then you could clone from central, from a friend, or a local clone on your own.