Fossil User Forum

fossil clone and open at the same time
Login

fossil clone and open at the same time

fossil clone and open at the same time

(1.1) By Alfred M. Szmidt (ams) on 2020-08-08 19:26:23 edited from 1.0 [source]

I realize that this has been raised multiple times, but it would be very convenient to be able to clone, and open a repository at the same time instead of doing:

fossil clone URI ~/Fossil/A.fossil
mkdir A
cd A
f open ~/Fossil/A.fossil

fossil clone URI ~/Fossil/B.fossil
mkdir B
cd B
f open ~/Fossil/B.fossil --nested

This is specially true if one uses several nested repositories, when writing down those instructions for a user to follow it becomes quite convulted. One also needs to write down instruction for each different platform. I have one project with several (~10) nested projects to keep things seperated for various reasons, and the setup becomes kinda complicated with the navigation of directories -- even if it is done in a script.

I'd like to suggest the addition of an extra option to the open command, --clone URI DIRECTORY switch so instead of having to do the above, it can be easily done as:

fossil open --clone URI A   ~/Fossil/A.fossil
fossil open --clone URI A/B ~/Fossil/B.fossil --nested

This would open A and B in A, respectivley A/B while also cloning the repository file into ~/Fossil/A.fossil. On error (e.g, if the repository file already exists, is open, etc) Fossil would abort early.

Would such a feature be accepted? I know that there has been arguments against it...

(2) By ravbc on 2020-08-05 10:04:17 in reply to 1.0 [link] [source]

I'd propose adding new optional parameter to fossil open instead to let you specify the directory where to open the repo.

Then your example instructions could look like this:

fossil clone URI ~/Fossil/A.fossil
fossil clone URI ~/Fossil/B.fossil
mkdir -p A/B
fossil open --workdir A ~/Fossil/A.fossil
fossil open --workdir A/B ~/Fossil/B.fossil --nested

(3) By Alfred M. Szmidt (ams) on 2020-08-05 10:12:29 in reply to 2 [link] [source]

That too would be a significant improvement in usability.

(4) By Warren Young (wyoung) on 2020-08-05 10:58:09 in reply to 1.0 [link] [source]

I think we should simply adopt Git's clone-and-open command by making the FILENAME parameter optional.

When you don't give that parameter, fossil will assume you want the cloned repo to be stored in $short-project-name/.fslrepo. (The variable is set via Admin → Configuration.)

This is one of the few areas where Git has a usability advantage over Fossil, and it'd be so easy to fix it.

A similar usability simplification can be done for Fossil's multiple-open feature.

With the above change, the literal way of opening a .fslrepo into another directory would be:

    mkdir ../release
    cd ../release
    fossil open ../trunk/.fslrepo

That's a bit verbose, which is what we were trying to avoid with the improvements to clone, so we could then extend Fossil to accept a directory name in place of the current FILENAME parameter, wherein it will try looking for a .fslrepo repo DB file within:

    mkdir ../release
    cd ../release
    fossil open ../trunk

That's a bit better, but we can extend it one step further: check whether we are in an open checkout, that --nested is not given, and that the named directory either doesn't exist or at least doesn't contain .fslrepo. Fossil can then assume that you want to open this repo into the named directory:

    fossil open ../release release

If you also don't give the ?VERSION? parameter, it can try treating the basename of the named target as a version string:

    fossil open ../release

That single command says, "I was given the name of a nonexistent file instead of a repo DB file, I'm in a checkout for trunk, and there is a release tag in this repo, so I think the user is asking me to open the "release" tag within the same repo tag into a new directory on this system."

(5) By Alfred M. Szmidt (ams) on 2020-08-05 11:10:40 in reply to 4 [link] [source]

I actually think that having the Fossil repository located in a different place is actually something that Fossil does right, and Git doesn't.  So me, personally -- I don't like this at all, even if this improves things slightly. :-/

(6) By ravbc on 2020-08-05 13:04:16 in reply to 4 [link] [source]

"I was given the name of a nonexistent file instead of a repo DB file, I'm in a checkout for trunk, and there is a release tag in this repo, so I think the user is asking me to open the "release" tag within the same repo tag into a new directory on this system."

This is way to much "magic" for my taste, ;-) And it would certainly cause confusion sooner or later.

Anyway I don't think that placing repo inside workdir is a reasonable thing to do. If the clone-and-open should be implemented, then I for sure would prefer storing the repo db at the same level as a workdir (eg. workdir as $short-project-name/ dir and repo db as $short-project-name.fossil file). But I really don't think that merging clone and open in one instruction is worth it. Especially since it's easily scriptable. And it would hide one of the advantages of fossil - possibility to have multiple checkouts from one db.

(7) By Stephan Beal (stephan) on 2020-08-05 15:19:42 in reply to 6 [link] [source]

This is way to much "magic" for my taste, ;-)

+1

Anyway I don't think that placing repo inside workdir is a reasonable thing to do.

+1. It's easy to corrupt a repo that way by performing options which globally affect all files. e.g. global text replace - i've ruined in-checkout repo dbs that way before, and i consider placing a repo db inside the checkout to belong to our unwritten list of "worst practices" (or "poor practices," at least - perhaps not "worst").

FWIW.

(8) By Warren Young (wyoung) on 2020-08-05 15:26:33 in reply to 6 [link] [source]

it would certainly cause confusion sooner or later.

Why would following the most popular DVCS on the planet be likely to cause more confusion than going down our own idiosyncratic path?

I don't think that placing repo inside workdir is a reasonable thing to do

None of what I proposed requires that you do that. This is a pure extension, not a change in existing functionality.

Personally, I won't be using the clone-and-open method myself very often, but what I would expect to do is give it as the default method to newbies using my projects. It changes what is currently 4 commands to a single command.

Experts will continue to work as they currently do, and newbies may grow to appreciate the extra power that the current methods afford.

Especially since it's easily scriptable.

That doesn't help in my case above. "Download this script, chmod +x it, put it in your PATH, and run it" doesn't save steps over the alternative.

it would hide one of the advantages of fossil - possibility to have multiple checkouts from one db.

I'd be hiding that detail from newbies who haven't yet acquired enough Fossil knowledge to care about the extra power, and who — let us be honest — are statistically unlikely to ever care about that extra power.

(9) By Warren Young (wyoung) on 2020-08-05 15:27:45 in reply to 7 [link] [source]

Fine: then put it in ~/.museum.

(10) By Alfred M. Szmidt (ams) on 2020-08-06 09:23:28 in reply to 9 [link] [source]

As a user I'd rather see a way of simplifying the means of clone+open, in anyway, than trying to get a complicated feature in that would get rejected from the onset.  The question I guess is what drh thinks, and what could convince him to add something that reduces the steps to clone+open.

(11) By ravbc on 2020-08-06 11:52:03 in reply to 8 [link] [source]

Why would following the most popular DVCS on the planet be likely to cause more confusion than going down our own idiosyncratic path?

Because this particular DVCS is one of the most non-intuitive tools out there? ;-)

I'd be hiding that detail from newbies who haven't yet acquired enough Fossil knowledge to care about the extra power, and who — let us be honest — are statistically unlikely to ever care about that extra power.

I'd say there are at least 2 kinds of newbies:

  1. someone, who never used any revision control system (or at least not a distributed one) - for such a person differentiating between clone and open should be easy enough with just the Quick Start Guide

  2. former git user (probably inexperienced in git) - instead of trying to imitate git it would be better to offer a "git converts" document (I thought there already is something like this, but it turns out that the gitusers only describes differences without showing a "translation" of typical git session into fossil command-line)

I also just checked and on the front page of fossil-scm.org there is a quick start (and a link for more detailed guide), but there is no "fossil for git users" cheat sheet (or a link to it). Even finding the gitusers doc isn't really easy, as it's not linked on frontpage, and not on the fossil-vs-git doc which is linked on the front page.

Maybe this specific topic (opening a repository after clone) could be also mentioned in the help for fossil clone (just a one sentence like: "clone does NOT create a checkout - use fossil open to do it after cloning")? Another idea: create a new command: intro (which should just show the quick start from front page, and maybe the new from-git cheat sheet) and make this single command stand out in fossil --help text?

Of course fossil is a do-ocracy so don't take my words as anything more than simple (and perhaps not even very sensible) suggestion. ;-)

(12) By Warren Young (wyoung) on 2020-08-06 13:23:20 in reply to 11 [link] [source]

Why would following the most popular DVCS on the planet be likely to cause more confusion than going down our own idiosyncratic path?

Because this particular DVCS is one of the most non-intuitive tools out there? ;-)

Overall, yes, but that doesn't mean Git has nothing to teach us.

Why shouldn't you be able to say fossil clone https://fossil-scm.org and have it do something useful? "Because Git does that" is a bad answer.

there are at least 2 kinds of newbies

There's a third, which says "Just tell me the minimum I need to get a copy of your software project, and 'learn Fossil' better not be one of the steps."

If you run any reasonably popular FOSS project, you will get this sentiment from your users, often expressed in some crypto-way, like "Why don't you just use GitHub?"

And yes, I'm aware we have one-way GitHub mirroring. I use that for my public projects. It just feels like giving up to say, "If you want the easiest method, say git clone https://github.com/tangentsoft/pidp8i".

Even finding the gitusers doc isn't really easy,

Docs → "Hints For Users With Prior Git Experience".

And you find that with a Ctrl/Cmd-F search on that page for "git", which is a reasonable thing to expect such users to do.

Another reasonable thing to expect is for users to type "git" into the search box at the top of that page. It's the second result.

not on the fossil-vs-git doc

Why would it be there? That's a comparison, meant to contrast the two tools' meaningful differences. It is not a transition guide.

(13) By ravbc on 2020-08-06 15:06:45 in reply to 12 [link] [source]

"If you want the easiest method, say git clone https://github.com/tangentsoft/pidp8i".

I'm not a developer (so I rarely have to work with git), but I'd say that if use of git is required, then it isn't "the easiest method" ;-) Downloading the tarball is way easier (for anyone, I dare to say).

Why would it be there?

Because that's the only document relating to git, that is linked on the homepage. Finding "Hints For Users With Prior Git Experience" on the Doc page isn't easy (as the whole page looks rather messy). Why not link it at least in the "Primary Documents" section? If you want to help git users, then don't make a git compatible command-line, but provide easily findable and concise documentation - of course this is only my opinion, not an order. ;-)

(14) By Richard Hipp (drh) on 2020-08-06 21:12:44 in reply to 1.0 [link] [source]

Below I will try to capture all of the various interface ideas for how to accomplish "clone" and "open" in a single command. (This post might be edited as new ideas emerge.)

Idea 1: (original by ams)

   fossil open --clone URI DIRECTORY ~/Fossils/a.fossil

This is the original proposal. A key problem is that command line arguments in Fossil take either 0 or 1 arguments, never 2 arguments.

Idea 2: (by ravbc)

   fossil clone URI ~/Fossils/A.fossil
   fossil open --workdir ~/A ~/Fossils/A.fossil

The --workdir option to "open" is a good idea regardless, I think. I extend ravbc's original suggestion by having Fossil automatically create the workdir directory if it does not already exist.

Idea 3: (by wyoung)

    fossil clone URI

By simply omitting the filename argument from the "clone" command, Fossil behaves like Git in that it clones the remote repository into the current directory and then immediately opens it. Warren suggests a name like ".fslrepo". You could do that, or you could name the repository based off the tail of the URI. One complication here is that all of the options for the "open" command now need to be duplicated in "clone", but only for cases where the filename argument is omitted. There is also the complaint that the repository ends up in the same directory as the checkout, though there is no reason this could not be combined with --workdir.

Idea 4: (new by drh)

    fossil open URI

If the argument to "open" is a URI instead of a filename, then clone that URI first, then open the clone. The name of the clone could be derived from the URI as above. We could also add a new "--repodir DIR" option that puts in cloned repository someplace other than at the top of the check-out, if that is desired. Combine that with --workdir and you have a very flexible command that does not require any "cd" or "mkdir" commands to set up your work environment. Maybe this method should automatically do a shallow clone (once shallow clones are implemented, which they are not as of yet) making it more useful (less bandwidth and CPU) for people who just want to get the latest source code.

(15) By Alfred M. Szmidt (ams) on 2020-08-06 21:19:42 in reply to 14 [link] [source]

Idea 4: (new by drh)

fossil open URI

Would this mean that there would/could be a slight difference between:

fossil open foo.fossil

and

fossil open file://foo.fossil

?

(Assuming that Fossil supports URI of this sort ...)

(16) By Richard Hipp (drh) on 2020-08-06 21:53:56 in reply to 15 [link] [source]

Yes. I think the second form would make a clone of the repo before opening it. It is not clear why you would ever want to do that, but I think that is what the syntax suggests.

(17) By Warren Young (wyetr) on 2020-08-06 22:10:05 in reply to 14 [link] [source]

The --workdir option to "open" is a good idea regardless, I think.

Yes. My only objection is that it solves a different problem. It's a good one to solve, but it's not the "we need a single short command to get a tree full of files" problem. It's 2 commands, and one of them is rather on the long side.

Warren suggests a name like ".fslrepo".

...Or ~/.museum/$short-project-name.fossil to solve worries over accidentally clobbering the repo file while hacking on the checkout directory. There's not much difference between the options to me, so outside objections tip the scales easily.

I can also be easily be swayed on the actual directory name. ~/.fossil is already taken, but ~/.fslrepos could work, for example.

there is no reason this could not be combined with --workdir.

If we do go with $short-project-name/.fslrepo, then --workdir doesn't solve the problem of colocating the working dir and the repo file. All it would override is the $short-project-name part. Useful, but orthogonal.

If we go with my second idea, using a default repo dir when no file name is given, then I think what you want to go with it is a --repodir option to override that part of the name:

  $ fossil clone --repodir /path/to/repos URI

If you want to set both the directory name and the file name, then you use the current syntax, passing what will be the optional ?FILENAME?.

fossil open URI

That'd be fine, too. My only reason for extending "clone" to do this is because Git does it that way, which means it follows the principle of least astonishment for Git users, which is approximately all potential Fossil users.

Still, it wouldn't be the first time Fossil and Git had the same function but on two different commands. (e.g. fossil up VERSION vs git checkout VERSION)

(18) By Warren Young (wyetr) on 2020-08-06 22:26:27 in reply to 17 [link] [source]

Further thoughts:

  1. If we ignore historical baggage, I do like fossil open URI better.

    It comes down to this: given that we have two commands, "clone" and "open", if we give the ability for one to implicit do the other's job, which way makes more sense?

    If you give "open" the ability to clone, then no one would be surprised, since in this hypothetical, Git has not already muddied the waters: Fossil has to have the repo to open it, so if you give it a URI to open, then of course it clones from that URI first, then opens it.

    If instead you give "clone" no file name to clone to, why does it guess at the file name and "open" it for you automatically? How does this make sense other than as "Because Git does it?"

    This feels like the sort of difference that would be easy to argue in the Fossil vs. Git doc, a design mistake Git made that we avoided.

    This doesn't change my earlier arguments: Git users will still pay a surprise penalty if we make this part of "open" rather than "clone". All I'm saying is that we have a good answer to "Why did you do it that way?"

  2. It is useful to combine both --repodir and --workdir:

    $ fossil open --repodir /path/to/repos \
                  --workdir ~/src/project/trunk \
                  https://example.com/project
    

    Implicit in that realization is that --workdir needs to implement mkdir -p semantics.

(19) By jamsek on 2020-08-07 04:43:45 in reply to 18 [link] [source]

I'm in complete agreement with Warren's reasoning: fossil open URI is
the best of the presented options for the reasons stated. My second
choice would be fossil clone URI but the implicit execution of the job
of fossil open is much less an expected behaviour than that of
fossil open cloning a repo when you actually pass it a URI. In fact,
you would expect that to occur so there's no surprises; not so with
the contraposition.

(20) By ravbc on 2020-08-07 09:08:39 in reply to 18 [link] [source]

Git users will still pay a surprise penalty if we make this part of "open" rather than "clone". All I'm saying is that we have a good answer to "Why did you do it that way?"

Using other command than git uses may have also the advantage that it will immediately draw attention to the functional differences between fossil and git, so git users will be less likely to take "shortcuts" in constructing fossil command-line.

(21) By Richard Hipp (drh) on 2020-08-07 14:05:20 in reply to 14 [link] [source]

"Idea 4" is now on trunk. Please test it out and report problems. Please also consider updating documentation to make use of the new capability, and/or at least suggest places where the documentation ought to be updated.

If there are no obvious problems, I'll publish new snapshots later today or tomorrow in order get the changes to a wider audience.

(22) By Warren Young (wyoung) on 2020-08-07 16:03:37 in reply to 21 [link] [source]

The naming of the repo as the "basename" from the URL means we're going to end up with a bunch of "index.cgi.fossil" repo DBs. If you're going to put it in the workdir, I still think .fslrepo is better, since it keeps the repo hidden from most commands.

If you don't like making it a hidden file, why then not clone to a temporary file name and read $short-project-name from its config table and use that? It's a logical extension of the variable's purpose.

Also, the current method doesn't completely solve the single-command clone-and-open wish since it clones and opens into CWD. I think it would be better if it opened into a directory named $short-project-name by default, since that saves a mkdir command. (It doesn't save a cd because you need that either way, so it factors out.)

(23) By Warren Young (wyoung) on 2020-08-07 16:12:10 in reply to 22 [link] [source]

The current scheme can also interfere with filename completion. Simple test case:

$ mkdir sqlite
$ cd sqlite
$ fossil open https://sqlite.org/src
$ vi src<TAB><TAB><TAB>

Long habits may lead you to expect you can hit Tab three times to get the trailing / and then an offer to get a list of files, but with Bash's default file name completion at least, it'll get stuck between the alternatives of src/ and src.fossil.

Consider this: if you were to create a histogram of commands given within a typical Fossil workdir, how many would be directed at the repo DB file vs against other files? Isn't the former sort way out in the long tail? The only one that comes readily to mind is multiple open, and if you're the sort to use that, you probably aren't using this feature to begin with.

(24) By anonymous on 2020-08-07 16:18:05 in reply to 21 [link] [source]

One on the practical advantages of Fossil is a simple ability to have multiple work directories using the same repository, basically multiple 'fossil open'. But the price for this convenience is a need for explicit placement of the repo file.

The current feature seems to reduce the cost, but at the same time complicating the use of multiple work dirs.

Instead I'd expect something that would first address the default location of the cloned repo. The mist reasonable place is a fixed directory in HOME, similar to how it's done for fossil config database. This location indeed should be configurable.

Then, there should be notion of Fossil repository default name. This is not obvious from a URL, but can be configurable.

Thus, the resulting workflow could be something like this:

#1. New repository of given name is created in default location; create work dir; open the repo
fossil init newrepo
cd newrepo
fossil info | grep repository:
 repository:  /home/user/the-user-data-dir/newrepo.fossil

#2. Open an existing repo by name in another work dir
mkdir work2 ; cd work2
fossil open newrepo work2branch
fossil info | grep repository:
 repository:  /home/user/the-user-data-dir/newrepo.fossil

#3. Clone a remote repo into default location, optionally override the local repo name; 

fossil clone URL repo2
cd repo2
fossil info | grep repository:
 repository:  /home/user/the-user-data-dir/repo2.fossil

## Reconfigure the default location and default extension
fossil set default-repository-dir /home/user/the-user-data-dir
fossil set default-repository-ext .fossil

## List the repositories in the default location; show repo name

fossil all ls --default
 newrepo: /home/user/the-user-data-dir/newrepo.fossil
 repo2: /home/user/the-user-data-dir/repo2.fossil

(25) By Alfred M. Szmidt (ams) on 2020-08-07 17:00:15 in reply to 21 [link] [source]

The check for for if we are already in a nested tree could probably be moved earlier, before fetching the repository? I'm thinking as a simpleton here,

$ fossil open URI
...
already within an open tree rooted at /home/ams

A simple user would here be confused, since there is no explicit error or information about what to do next. Nor can one do a simple "up arrow amend, and enter" action where you add --nested -- since the Fossil repository is already fetched.

(26) By Alfred M. Szmidt (ams) on 2020-08-07 17:03:50 in reply to 14 [link] [source]

Idea 5:

   fossil create URI DIRECTORY ???

Another option is to add a new command (create might be a bad namn) that does the setup, how this command should look I'm not sure though.

(27) By Richard Hipp (drh) on 2020-08-07 21:21:37 in reply to 22 [link] [source]

The fossil clone mechanism ignores extra terms on the end of the path. So you can cause the clone to be named anything you want simply by appending a new name onto the end of the URI. Example:

    fossil open https://fossil-scm.org/home/my-fossil-clone

This results in a clone named my-fossil-clone.fossil.

(28) By John Rouillard (rouilj) on 2020-08-07 22:55:43 in reply to 23 [link] [source]

Hi Warren:

> $ fossil open https://sqlite.org/src
> $ vi src<TAB><TAB><TAB>

I think it would be better if the open happened in a subdir. So ./src would be the working directory for src.fossil. Then you can get proper tab completion for the cd command with cd src then vi <tab>....

This also makes running fossil from a directory containing src.fossil fail. So running fossil clean will do nothing damaging (actually it seems to do nothing anyway, wonder why).

Also I wonder if we could make --repodir settable via an environment variable as well. So

$ export FOSSIL_REPO_DIR=~/.museum
$ fossil open  https://sqlite.org/src

acts like

$ fossil open --repodir ~/.museum https://sqlite.org/src
That way you can set it once and it applies to all fossil invocations.

Alternatively it could live in ~/.fossil. This would be of use to those who use fossil natively rather than a driveby open.

The driveby user is probably happy leaving src.fossil where it is. However a fossil user probably has a museum where the fossils should congregate. It's kind of tricky to relocate src.fossil and not break the src working directory. (Maybe a reference to the command to relocate .fossil in the open help text could be useful? Where would a good place to document relinking a moved .fossil file be? Maybe in the error message:

repository does not exist or is in an unreadable directory: .../sqlite/./src.fossil

could change to:

repository does not exist or is in an unreadable directory: ...sqlite/src.fossil.

See also fossil help test-move-repository.

Hmm, maybe that command is not so useful after all:

$ fossil test-move-repository sqlite.fossil
repository does not exist or is in an unreadable directory: .../sqlite/./src.fossil

(29) By Alfred M. Szmidt (ams) on 2020-08-08 08:11:59 in reply to 21 [link] [source]

Slightly surprising behaviour is when passing --repodir -- the location is the working directory it seems, so when passing a relative path name surprising things can happen.

$ fossil open --repodir . --nested --workdir FOO URI/FOO
...
repository does not exist or is in an unreadable directory: ./FOO.fossil

So far using this I've found it to be very nice, the only slightly(!) suprising thing is that as a (new) user you might expect that fossil open URI will open things in a sub-directory -- so it is rather important to pass --workdir unless you want to bomb your CWD.

I realize that this is expected, since that is how the fossil open command works, and doing it differently would make fossil open FILE and fossil open URI exhibit different behavior.

(30) By Richard Hipp (drh) on 2020-08-08 15:01:52 in reply to 29 [link] [source]

a (new) user might expect that fossil open URI will open things in a sub-directory

As far as I know, Git is the only software that works that way. Other dearchiver programs (tar, unzip) will happily bomb the CWD if you ask them too. The convention with tar and zip is that when you build the archive, you archive just one subdirectory, so when you extract you get back just that one subdirectory. But that is just a usage convention. You can easily build a flat tarball or ZIP archive, and when you extract such a thing, it bombs your CWD. There is no automatic creation of subdirectories.

So from my point of view, Git is the outlier here. Nevertheless, it would be prudent to highlight this difference in beginner-oriented Fossil docs.

(31) By Stephan Beal (stephan) on 2020-08-08 16:23:16 in reply to 30 [link] [source]

As far as I know, Git is the only software that works that way. Other dearchiver programs (tar, unzip) will happily bomb the CWD if you ask them too.

Having just been bitten by this when trying out open URL for the first time...

Don't hold this against me, but git does this right.

It seems to me that the normal usage of open URL will be something along the lines of:

fossil open https://.../foo # forgot, again, --workdir
cd foo   # no such directory
ls       # doh...
ls -la   # find the hidden files
rm -fr ...carefully-selected list of files... .fslckout .fossil-settings
mkdir foo
cd foo
fossil open ../foo.fossil

Granted, that's now a misuse, but i predict that --workdir is going to be forgotten a great many times before it's internalized.

That saved me no real effort over:

fossil clone https://.../foo foo.fossil
mkdir foo
cd foo
fossil open ../foo.fossil

If open URL is going to unpack in the current directory by default (i agree that does align with its historical usage), a slight shorthand which re-uses the tail of the URL or the project's short-form name for the workdir would simplify usage over the current duplication of that name. Something align the lines of:

fossil open https://.../foo --subdir
==> equivalent to one of:
fossil open https://.../foo --workdir foo
fossil open https://.../foo --workdir short-project-name

Regarding the tail of the URL: Warren's not wrong about us ending up with lots of repos named index.cgi.

Alternately, default workdir to the tail or short name and allow --workdir . to use the bomb-this-dir approach (which seems likely to be only rarely desirable).

(32) By John Rouillard (rouilj) on 2020-08-08 16:32:56 in reply to 31 [link] [source]

+1

(33) By Warren Young (wyoung) on 2020-08-08 16:34:45 in reply to 30 [link] [source]

I retract my wish for automatic directory creation in the "open URI" case.

It would be different if we weren't overloading open functionality, but ams is right: we can't have open behaving so differently based on parameter glob sniffing.

If we're going to have a Git-like "open and clone into new directory," it should probably be a new command, neither open nor clone.

(34) By Andy Bradford (andybradford) on 2020-08-08 16:42:15 in reply to 33 [link] [source]

> If we're going to have a Git-like "open and clone into new directory,"
> it should probably be a new command

How about "fossil cloneandopen"?

Andy

(35) By Andy Bradford (andybradford) on 2020-08-08 16:45:37 in reply to 33 [link] [source]

I retract my wish for automatic directory creation in the "open URI" case.

I agree that having "fossil open" be responsible for blindly cloning is fraught with peril. Specifically, it takes what used to be an error condition, one that would catch someone from doing the wrong thing, and make it now something that results in potentially bad behavior.

I may accidentally type "fossil open http://some/url" and suddenly find things in a bad way.

Andy

(36) By Warren Young (wyoung) on 2020-08-08 17:06:24 in reply to 34 [link] [source]

How about "fossil cloneandopen"?

No, because "clone" and "open" mean something specific in terms of Fossil.

This new command will let us create new semantics without breaking old ones, but we also don't want to be redefining Fossil terms of art.

How about "fossil get"?

(37) By Warren Young (wyoung) on 2020-08-08 17:18:33 in reply to 31 [link] [source]

git does this right.

Keep in mind that Git has always open-and-cloned into a new directory on git clone. Fossil never has, and open has semantics going back to Day 1 that we can't reasonably change.

While I do still want Git-style cloning for ease of use and transitioning from Git, I realize now that it needs to be a new command. (e.g. fossil get)

The main problem I have with the current version of this feature is just that I think the repo should be hidden away somewhere instead, whether that's .fslrepo, ~/.museum/$basename.fossil, or whatever.

Programs that work on local files and on URIs equally generally work by downloading a copy somewhere and then operating on it locally. I don't know of a single one that puts the downloaded copy in CWD. It's always hidden away somewhere.

Examples:

  $ vim scp://example.com/path/to/file.txt
  $ curl http://example.com/package.tar.gz | tar xvf -

The primary difference in Fossil from these cases is simply that Fossil needs to keep the repo file around persistently, not as a temporary. That doesn't mean it should be readily visible in CWD, though.

(38) By Richard Hipp (drh) on 2020-08-08 17:33:13 in reply to 31 [link] [source]

bitten by this when trying out open URL for the first time...

The latest trunk refuses to open a URL into a non-empty directory. It tells you to use "--workdir ." to override the restriction.

It is simple enough to change this so that it refuses to open anything in a non-empty directory without either --workdir or --keep. But that might break legacy.

(39) By Richard Hipp (drh) on 2020-08-08 17:40:38 in reply to 36 [link] [source]

I usually type "fossil get" when I was meaning to type "fossil git", in as much as they are homophones.

(40) By Richard Hipp (drh) on 2020-08-08 18:20:04 in reply to 38 [link] [source]

Further refinement: The "fossil open" command now always requires the working directory to be empty unless either the either the --keep or the --force flag is used. This makes it harder to bomb your CWD by mistake regardless of whether you are using the older or newer form for "fossil open".

(41) By Stephan Beal (stephan) on 2020-08-08 18:23:12 in reply to 39 [link] [source]

I usually type "fossil get" when I was meaning to type "fossil git", in as much as they are homophones.

In your dialect, maybe ;). (Okay, the difference is admittedly subtle in most other dialects.)

i like Warren's suggestion of "get", but yeah, it might make speaking about the features potentially ambiguous, depending on one's dialect.

fossil fetch?

(Welcome back, by the way! Google suggested that you'd be away for "1-4 weeks.")

(42) By anonymous on 2020-08-08 18:29:30 in reply to 37 [link] [source]

Git repository database names by definition are the same (.git). Git fuses the notion of repository together with work directory under the same named corresponding to the containing directory. This convention applies separately over local and remote namespaces. These two namespaces are technically reconciled in git remote settings.

In case of Fossil, there's a single unique identifier common across the local and the remote namespaces -- that is PROJECT-ID. So far PROJECT-ID is used only internally, not visible in the file-system.

Fossil fuses the notion of repository together with the repository database. At the same time, it detaches the work directory from the notion of the repository, this allows one to have several work directories attached to the same database/repository.

Thus the Fossil work directory name as such is no longer representative of the repository name.

There needs to be an additional naming equivalent, perhaps tied to PROJECT-ID. Then it could be used to name the repository database and in case of the clone/open this name can be used to automatically create the work directory.

If such repository name-tag (??) could be defined in repository configuration, it may be transmitted at client handshake. By default it may be used to name the local Fossil clone repository database and the corresponding work directory.

Richard suggested that a remote URL ending path may be arbitrarily used in-lieu of repository name, but I think it would be more consistent if it were defined on the configuration level.

(43.4) By Alfred M. Szmidt (ams) on 2020-08-08 19:18:39 edited from 43.3 in reply to 41 [link] [source]

So I'm on the fence, I'm starting to like the current behavior. But one slight thing that annoys me is that the very slight difference between "fossil open URI" and "fossil open FILE" -- and that is that they are semantically different.

On the naming of a entirely new option, what about "fossil checkout"? That rhymes with the terminology overall...

And then I'm thinking that "fossil checkout URI" and "fossil checkout FILE" would behave exactly the same, but in the case of a URI it would do a "fossil clone". Then, it would be "mkdir PROJECT-SHORT-NAME; fossil open REPOSITORY --workdir PROJECT-SHORT-NAME". This would mean that reverting part of the new "fossil open URI" would be required (cloning the URI, and --repodir), but keeping the new --workdir.

This could, without breaking peoples workflows, be incorporated with Warren Youngs suggestion about having a ~/.museum kind of place. Making it possible to open multiple repositories from the same URI/FILE-REPOSITORY -- without refetching things (there could even be an implicit "fossil sync" here). E.g.,

fossil checkout http://example.com/REPO
fossil checkout http://example.com/REPO BRANCH --workdir REPO-BRANCH

In the second case, it would reuse ~/.museum/REPO.fossil.

(44) By Richard Hipp (drh) on 2020-08-08 20:30:16 in reply to 43.4 [link] [source]

There is already a "fossil checkout" command. But I suppose we could overload it too....

(45) By Alfred M. Szmidt (ams) on 2020-08-08 20:43:25 in reply to 44 [link] [source]

I looked at the output of "fossil help" and did not see anything. :-(

(46) By Richard Hipp (drh) on 2020-08-08 20:59:15 in reply to 45 [link] [source]

The "fossil help" output is deliberately abbreviated to try to avoid overwhelming the reader. Use the -a option to see the complete list of normal commands:

$ fossil help -a
3-way-merge    clean          hook           redo           tag          
add            clone          http           remote-url     tarball      
addremove      close          import         rename         ticket       
alerts         co             info           reparent       timeline     
all            commit         init           revert         tls-config   
amend          configuration  leaves         rm             touch        
annotate       dbstat         login-group    rss            ui           
artifact       deconstruct    ls             scrub          undo         
attachment     delete         md5sum         search         unpublished  
backoffice     descendants    merge          server         unset        
backup         diff           mv             settings       unversioned  
bisect         export         new            sha1sum        update       
blame          extras         open           sha3sum        user         
branch         finfo          pop3d          shell          uv           
bundle         forget         praise         smtpd          version      
cache          fts-config     publish        sql            whatis       
cat            gdiff          pull           sqlar          wiki         
cgi            git            purge          sqlite3        zip          
changes        grep           push           stash        
checkout       hash-policy    rebuild        status       
ci             help           reconstruct    sync         

Use --test to see 134 more unsupported "test" commands.

(47) By Alfred M. Szmidt (ams) on 2020-08-08 20:59:21 in reply to 40 [link] [source]

I suggest the following fixes to the documentation:

** COMMAND: open
**
** Usage: %fossil open REPOSITORY ?VERSION? ?OPTIONS?
**
** Open a new connection to the repository name REPOSITORY.  A
** checkout for the repository is created with its root at the current
** working directory, or in DIR if the "--workdir DIR" option is used.
** If VERSION is specified then that version is checked out.
** Otherwise the most recent check-in on the main branch (usually
** "trunk") is used.
**
** REPOSITORY can be the filename for a repository that already exists
** on the local machine or it can be a URI for a remote repository.
** If REPOSITORY is a URI, the remote repository is first cloned, then
** the clone is opened.  The clone will be stored in the current
** directory, or in DIR if the "--repodir DIR" option is used.  The
** name of the clone will be taken from the last term of the URI.  For
** "http" and "https" URI scheme names, you can append an extra term
** on the end to get any repository name you like.  For example:
**
**     fossil open https://fossil-scm.org/home/new-name
**
** The base URI for cloning is "https://fossil-scm.org/home".  The extra
** "new-name" term means that the cloned repository will be called
** "new-name.fossil".
**
** Options:
**   --empty           Initialize checkout as being empty, but still connected
**                     with the local repository. If you commit this checkout,
**                     it will become a new "initial" commit in the repository.
**   --force           Continue with the open even if the working directory is
**                     not empty.
**   --force-missing   Force opening a repository with missing content
**   --keep            Only modify the manifest and manifest.uuid files
**   --nested          Allow opening a repository inside an opened checkout
**   --repodir DIR     If REPOSITORY is a URI that will be cloned, store
**                     the clone in DIR rather than in "."
**   --setmtime        Set timestamps of all files to match their SCM-side
**                     times (the timestamp of the last checkin which modified
**                     them).
**   --workdir DIR     Use DIR as the working directory instead of ".". The DIR
**                     directory is created if it does not previously exist.
**
** See also: close

Some minor spelling errors, replacing double-quote with single quote, and rewording the second paragraph slightly.

(48) By Richard Hipp (drh) on 2020-08-08 21:01:17 in reply to 47 [link] [source]

The help text has changed quite a bit from your baseline already. Please consider grabbing the latest code and posting a diff of your changes.

(49) By Alfred M. Szmidt (ams) on 2020-08-08 21:14:55 in reply to 48 [link] [source]

Here is another try.

** COMMAND: open
**
** Usage: %fossil open REPOSITORY ?VERSION? ?OPTIONS?
**
** Open a new connection to the repository name REPOSITORY.  A checkout
** for the repository is created with its root at the current working
** directory, or in DIR if the "--workdir DIR" is used.  If VERSION is
** specified then that version is checked out.  Otherwise the most recent
** check-in on the main branch (usually "trunk") is used.
**
** REPOSITORY can be the filename for a repository that already exists on the
** local machine or it can be a URI for a remote repository.  If REPOSITORY
** is a URI in one of the formats recognized by the [[clone]] command, then
** remote repoistory is first cloned, then the clone is opened.
** The clone will be stored in the current directory, or in DIR if the "--repodir DIR" option is used.
** The name of the clone will
** be taken from the last term of the URI.  For "http" and "https" URI scheme names, you
** can append an extra term on the end to get any repository name you like.
** For example:
**
**     fossil open https://fossil-scm.org/home/new-name
**
** The base URI for cloning is "https://fossil-scm.org/home".  The extra
** "new-name" term means that the cloned repository will be called
** "new-name.fossil".
**
** Options:
**   --empty           Initialize checkout as being empty, but still connected
**                     with the local repository. If you commit this checkout,
**                     it will become a new "initial" commit in the repository.
**   --force           Continue with the open even if the working directory is
**                     not empty.
**   --force-missing   Force opening a repository with missing content
**   --keep            Only modify the manifest and manifest.uuid files
**   --nested          Allow opening a repository inside an opened checkout
**   --repodir DIR     If REPOSITORY is a URI that will be cloned, store
**                     the clone in DIR rather than in "."
**   --setmtime        Set timestamps of all files to match their SCM-side
**                     times (the timestamp of the last checkin which modified
**                     them).
**   --workdir DIR     Use DIR as the working directory instead of ".". The DIR
**                     directory is created if it does not exist.
**
** See also: [[close]], [[clone]]

Here is the diff to highlight the changes,

Index: src/db.c
==================================================================
--- src/db.c
+++ src/db.c
@@ -3089,39 +3089,39 @@
 ** check-in on the main branch (usually "trunk") is used.
 **
 ** REPOSITORY can be the filename for a repository that already exists on the
 ** local machine or it can be a URI for a remote repository.  If REPOSITORY
 ** is a URI in one of the formats recognized by the [[clone]] command, then
-** remote repo is first cloned, then the clone is opened.
-** The clone will be stored in the current directory, or in an alternative
-** directory specified by the --repodir option.  The name of the clone will
-** be taken from the last term of the URI.  For http: and https: URIs, you
+** remote repoistory is first cloned, then the clone is opened.
+** The clone will be stored in the current directory, or in DIR if the "--repodir DIR" option is used.
+** The name of the clone will
+** be taken from the last term of the URI.  For "http" and "https" URI scheme names, you
 ** can append an extra term on the end to get any repository name you like.
 ** For example:
 **
 **     fossil open https://fossil-scm.org/home/new-name
 **
-** The base URI for cloning is 'https://fossil-scm.org/home'.  The extra
-** 'new-name' term means that the cloned repository will be called
-** 'new-name.fossil'.
+** The base URI for cloning is "https://fossil-scm.org/home".  The extra
+** "new-name" term means that the cloned repository will be called
+** "new-name.fossil".
 **
 ** Options:
 **   --empty           Initialize checkout as being empty, but still connected
 **                     with the local repository. If you commit this checkout,
 **                     it will become a new "initial" commit in the repository.
 **   --force           Continue with the open even if the working directory is
-**                     not empy.
+**                     not empty.
 **   --force-missing   Force opening a repository with missing content
 **   --keep            Only modify the manifest and manifest.uuid files
 **   --nested          Allow opening a repository inside an opened checkout
 **   --repodir DIR     If REPOSITORY is a URI that will be cloned, store
 **                     the clone in DIR rather than in "."
 **   --setmtime        Set timestamps of all files to match their SCM-side
 **                     times (the timestamp of the last checkin which modified
 **                     them).
 **   --workdir DIR     Use DIR as the working directory instead of ".". The DIR
-**                     directory is created if it does not previously exist.
+**                     directory is created if it does not exist.
 **
 ** See also: [[close]], [[clone]]
 */
 void cmd_open(void){
   int emptyFlag;

(50) By jamsek on 2020-08-09 03:19:24 in reply to 40 [link] [source]

I like this refinement. Warren got me thinking with the comparisons to
existing progammatic behaviour in the Unix toolset, which made me
question whether the --repodir option should actually be a required
argument if REPOSITORY is a URI; for example, rather than:

fossil open --repodir ~/museum https://fossil-scm.org/home/new-name

the command would be:

fossil open https://fossil-scm.org/home/new-name ~/museum

Similar to scp user@remote:~/path/to/foo ~/path/to/bar.

Here's a quick diff for testing:

Index: src/db.c
==================================================================
--- src/db.c
+++ src/db.c
@@ -3366,26 +3366,26 @@
 }

 /*
 ** COMMAND: open
 **
-** Usage: %fossil open REPOSITORY ?VERSION? ?OPTIONS?
+** Usage: %fossil open REPOSITORY ?VERSION? ?OPTIONS? ?DIR?
 **
 ** Open a new connection to the repository name REPOSITORY.  A checkout
 ** for the repository is created with its root at the current working
 ** directory, or in DIR if the "--workdir DIR" is used.  If VERSION is
 ** specified then that version is checked out.  Otherwise the most recent
 ** check-in on the main branch (usually "trunk") is used.
 **
 ** REPOSITORY can be the filename for a repository that already exists on the
 ** local machine or it can be a URI for a remote repository.  If REPOSITORY
-** is a URI in one of the formats recognized by the [[clone]] command, then
-** remote repo is first cloned, then the clone is opened. The clone will be
-** stored in the current directory, or in DIR if the "--repodir DIR" option
-** is used. The name of the clone will be taken from the last term of the URI.
-** For "http:" and "https:" URIs, you can append an extra term to the end of
-** the URI to get any repository name you like. For example:
+** is a URI in one of the formats recognized by the [[clone]] command, the DIR
+** argument must also be given to provide the directory in which the cloned
+** REPOSITORY will be stored. Fossil will first clone the remote repo into DIR
+** before opening the clone. The name of the clone will be taken from the last
+** term of the URI. For "http:" and "https:" URIs, you can append an extra term
+** to the end of the URI to get any repository name you like. For example:
 **
 **     fossil open https://fossil-scm.org/home/new-name
 **
 ** The base URI for cloning is "https://fossil-scm.org/home".  The extra
 ** "new-name" term means that the cloned repository will be called
@@ -3398,12 +3398,10 @@
 **   --force           Continue with the open even if the working directory is
 **                     not empty.
 **   --force-missing   Force opening a repository with missing content
 **   --keep            Only modify the manifest and manifest.uuid files
 **   --nested          Allow opening a repository inside an opened checkout
-**   --repodir DIR     If REPOSITORY is a URI that will be cloned, store
-**                     the clone in DIR rather than in "."
 **   --setmtime        Set timestamps of all files to match their SCM-side
 **                     times (the timestamp of the last checkin which modified
 **                     them).
 **   --workdir DIR     Use DIR as the working directory instead of ".". The DIR
 **                     directory is created if it does not exist.
@@ -3419,11 +3417,11 @@
   int setmtimeFlag;              /* --setmtime.  Set mtimes on files */
   int bForce = 0;                /* --force.  Open even if non-empty dir */
   static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };
   const char *zWorkDir;          /* --workdir value */
   const char *zRepo = 0;         /* Name of the repository file */
-  const char *zRepoDir = 0;      /* --repodir value */
+  const char *zRepoDir = 0;      /* Name of repository directory */
   char *zPwd;                    /* Initial working directory */
   int isUri = 0;                 /* True if REPOSITORY is a URI */

   url_proxy_options();
   emptyFlag = find_option("empty",0,0)!=0;
@@ -3430,11 +3428,10 @@
   keepFlag = find_option("keep",0,0)!=0;
   forceMissingFlag = find_option("force-missing",0,0)!=0;
   allowNested = find_option("nested",0,0)!=0;
   setmtimeFlag = find_option("setmtime",0,0)!=0;
   zWorkDir = find_option("workdir",0,1);
-  zRepoDir = find_option("repodir",0,1);
   bForce = find_option("force",0,0)!=0;
   zPwd = file_getcwd(0,0);


   /* We should be done with options.. */
@@ -3450,10 +3447,13 @@
    || sqlite3_strglob("file:*", zRepo)==0
   ){
     isUri = 1;
   }

+  if (isUri && g.argc != 4)
+    usage("REPOSITORY-URI DIR");
+
   /* If --workdir is specified, change to the requested working directory */
   if( zWorkDir ){
     if( !isUri ){
       zRepo = file_canonical_name_dup(zRepo);
     }
@@ -3486,10 +3486,11 @@
     int i;            /* Loop counter */
     int rc;           /* Result code from fossil_system() */
     Blob cmd;         /* Clone command to be run */
     char *zCmd;       /* String version of the clone command */

+    zRepoDir = g.argv[3];
     zUri = zRepo;
     zNewBase = fossil_strdup(file_tail(zUri));
     for(i=(int)strlen(zNewBase)-1; i>1 && zNewBase[i]!='.'; i--){}
     if( zNewBase[i]=='.' ) zNewBase[i] = 0;
     if( zRepoDir==0 ) zRepoDir = zPwd;

One potential problem is if opening repositories from a URI can also be
passed a ?VERSION?, some more code would be needed to handle that
particular use case properly.

This approach of enforcing a repository directory might better mimic
existing behaviour, and create a more consistent environment.

(51) By Florian Balmer (florian.balmer) on 2020-08-18 11:57:16 in reply to 40 [link] [source]

I would like to suggest adding a short variant for the new --force option. I keep my global build scripts in separate repositories, so my default work-flow is to open repositories in non-empty directories prepopulated with the build scripts. So I'm not happy with the new default behavior, but a short option would save me some typing, at least.