HNHacker News
TopNewBestAskShowJobs

wyoung2

168 karma · joined December 15, 2015

submissionscomments
wyoung2··on Get Started with F# as a C# developer
> If you want to get things done in .NET Core, use C#.

And if you want to get things done in F#, don't use .NET Core. :) Good thing .NET Core is merely the .NET du jour, not the only .NET.

> If anyone doubts this, compare the number of F# repos to Elixir/Scala on Github.

Challenge accepted. It turns out that GitHub's advanced search page can answer questions like this directly:

Projects written in F#: 4,246 (https://github.com/search?utf8=%E2%9C%93&q=language%3AF%23&t...)

Projects written in Elixir: 4,667 (https://github.com/search?utf8=%E2%9C%93&q=language%3AElixir...)

That's less than 10% higher. Plus, I'd guess there is a bias against closed-source projects in that result, owing to the nature of .NET.

Scala is indeed a lot higher at 38,424 projects, though I wonder how many of the complaints about F# from C# users apply apply equally to Scala. (e.g. Poor GUI builder support, no native compiler, etc.)

F#'s language representation on GitHub is also nearly equal to that of OCaml, a much older language.

I'd say that's a pretty good showing for a new-ish language. Not everything's going to pop to the top like Swift, which IMHO is a "people in Hell want ice water" reaction to Objectionable C.

wyoung2··on Get Started with F# as a C# developer
> I'll take MS's commitment to F# seriously when they stop treating it like a 2nd class citizen.

If you're waiting for Microsoft to give exactly equal resources to both C# and F#, you'll be waiting forever. Just like you'll be waiting for equal resources given to Visual Basic, TypeScript, PowerShell, VBA...

Equal splits never happen in a competitive situation. 60/40 splits are much more common, but here in this case, we have many first-party languages, so you'd expect a more complicated split, just as we see now.

> .NET Core 2.0 is in preview and there is ZERO support for F# with .NET Core in Visual Studio 2017

That's coming in the next update. (https://blogs.msdn.microsoft.com/visualstudio/2017/05/10/upd...) You've been able to run F# in .NET Core in preview form going back to the 1.1 series.

My opinion is that .NET Core is the real bag of hurt here, not F#. Stop sticking your hand in that blender. Use Mono and open source F# until .NET Core stops changing the world on each release.

> VSCode is no Visual Studio

And neither one is Vim.

Are we really going to have another editor war? :)

wyoung2··on Get Started with F# as a C# developer
> Were your fellow developers interested in F#?

I was sole developer on that project.

But here's a thought for you: you can only achieve mediocrity if all choices require 100% buy-in from all interested parties.

> I have found most people simply don't care and don't want to learn it.

No one likes to have their cheese moved. But cheese moves nevertheless.

> We did functions 30 years ago.

Most people saying that probably don't realize that what computer programmers call "functions" are not what mathematicians call "functions."

The reason FP is becoming popular now is that the distinction now matters much more than ever in today's multicore world, where multiprocessing is often the only practical way to make software substantially faster.

wyoung2··on Get Started with F# as a C# developer
Just to add to what the others have said:

1. Immutable values by default avoids whole categories of problems. Just for one example, you can't have a data race between two threads if all the public values accessible from each thread are guaranteed immutable.

2. F# forces all cases to be handled. You've doubtless run into C# code that has a switch statement that doesn't have cases for all possible inputs, and no default case. F# doesn't have a direct equivalent of "switch" at all, but it does enforce completeness in the equivalents it does have. For example, it's illegal in F# to say something like "if foo > 1 then ... elif foo < 1 ..." since that leaves the 0 case unhandled. This is not just about better compiler warnings: it's required by the very fact that "if/else" is an expression, not a statement, so all branches must produce a value for all inputs.

3. F# has units of measure data types. Ever had an application bug because you've incorrectly passed a bare "int" value holding milliseconds to a function expecting seconds? I have. F# lets you define your units as part of the data type, so that it's a compiler error to pass milliseconds to a function expecting seconds.

I could go on, but as you can see, there really are substantial differences in practice between F# and C# code.

wyoung2··on Get Started with F# as a C# developer
I can't share the code with you, but I did just that on a proprietary app for my company. Only the GUI shell of the app is in C#, and that only because the GUI builder features of Visual Studio can only generate C# code.

All of the "real" code in that app is in an F# library, which you add to the Visual Studio solution just like you would any other C# helper library. When you add a source file to that library, it's an F# source file, and it's built with the F# compiler into the library, which is then linked with the C# "main" program.

There are a few tricky parts, owing to the substantial differences between C# and F#. They all come down to the fact that there are aspects of both C# and F# that don't map naturally to the other. While there may be low-level .NET or IL ways to force the call, it's better to restrict your use of each language at the boundary between the two parts of the program.

Some examples:

1. F# has two ways of passing parameters to a function called the tuple and curry forms. Curried functions are the full-power form, but C# can't call them directly, so any function or method you want to export to the C# side must use the tuple form. At a superficial level, the only difference is some parentheses and commas, but at a low level, you're purposely nerfing the F# function to allow C# to call it. This is not an area you can avoid knowing about, since all of .NET uses tupled calling form, being written for C# initially.

2. F# has several native data types that have no direct implementation in C#. Some newer versions of C# have .NET extensions to allow them to manipulate values of these types given to the C# side from the F# side, but given a choice, it's often simpler to restrict the set of data types you define the interface between the two in terms of. That is, you generally don't want to allow discriminated unions, records, tuples, or function values through the boundary, if you can help it. Use data types C# copes with better: classes, structures, lists, and arrays instead.

3. C# code often makes use of null values, which are...well, "sinful" in F#. It is possible to use null in F#, but strongly recommended against, since F# is all about definite value states, and null adds an element of indefinite-ness to the application. You can choose either to allow null values through the C# to F# boundary or enforce the F# side's wish not to accept them at the boundary. Your choice.

4. Once you get into the F# way of doing things, you start to become more choosy about the C# libraries you use from F#, since some are more acceptable from an F# standpoint than others. You start to avoid libraries that have mutable values flying around everywhere, methods with side effects, etc. Some C# libraries are outright annoying to use, because you have to continually cast away so much of the F# value in order to use them. Fortunately, .NET itself is generally pretty good in this regard. The NuGet world shows less restraint here.

wyoung2··on SQLite small blob storage: 35% Faster Than the Filesystem
As I understand it, drh simply disabled Windows Defender entirely for these tests.

SQLite gets an additional advantage with Defender enabled because Defender doesn't try to scan inside the SQLite DB file for the sub-files, whereas with separate files, Defender must at least look at each file's header to determine whether it's a potentially dangerous file type.

While I was vetting this article, I did some of my own tests, and I found that simply excluding the directory containing the test tree was sufficient to get the same benefit.

My point in other posts here is that you don't need to disable Defender to get this benefit when you use SQLite.

But let's be clear: the 35% claimed performance benefit has nothing to do with Windows Defender. That's a wholly separate issue. Defender pays more attention to a pile of individual files than to an amalgamation of that same data into a single file, and this magnifies SQLite's advantages, but it is not the source of the advantage the linked report talks about.

wyoung2··on SQLite small blob storage: 35% Faster Than the Filesystem
> What happens if process A reads from a file while process B writes it?

If process B started first, the writer blocks access to the table being written to, so the reader waits for the writer to complete. There are timeout and retry behaviors, but within those configurable limits, that's what happens.

You can make SQLite behave as you worry about if you set the retries to 0 and timeout to 0, but that's not the default.

wyoung2··on SQLite small blob storage: 35% Faster Than the Filesystem
My contention was that this article is about least-effort methods (i.e. fopen() vs default SQLite) so a lot of Windows SQLite users are going to have Defender (or heaven help them, something much worse) installed.

Once you start getting into optimizations, much of this article starts to sway back and forth. Put enough effort into optimization, and you can outdo SQLite for a specific application, simply because SQLite isn't magic, it's just C. Well-written and highly-optimized C, but purpose-written code always has the potential to do better than general-purpose code.

The point of SQLite in general and this report in specific is that you get a lot of performance, power, and safety for free with SQLite as opposed to `fopen()` and such. Good performance while antimalware interferes is just one way this manifests.

wyoung2··on SQLite small blob storage: 35% Faster Than the Filesystem
See section 2.1 in the report: the Win10 and Win7 installations are on different hardware.

If you have a dual-boot Win10/7 box, it's easy to run the test yourself.

wyoung2··on SQLite small blob storage: 35% Faster Than the Filesystem
> What about mixed delete/write/read workloads?

The source code to the test program is part of the SQLite source tree. It should be fairly easy to modify it to test the scheme you have in mind.

> How well does SQLite deal with fragmentation?

SQLite operates a lot like a modern filesystem: tree-based indexing structures, writes go to empty spaces, deletes leave holes that may later be filled by inserts, etc.

SQLite has active mechanisms to reduce fragmentation on the fly: b-tree page defragmentation (https://www.sqlite.org/fileformat.html) and auto-vaccuum (https://www.sqlite.org/pragma.html#pragma_auto_vacuum) being the main ones. If the DB file gets too fragmented, you can run a manual VACCUM (https://www.sqlite.org/lang_vacuum.html) on it.

wyoung2··on SQLite small blob storage: 35% Faster Than the Filesystem
> I don't know how SQLite handles concurrency.

Why remain in ignorance? There are several articles in the SQLite documentation that address concurrency:

https://www.sqlite.org/wal.html https://www.sqlite.org/lockingv3.html https://www.sqlite.org/whentouse.html

> Somehow I would expect that if I simply replaced it with SQLite, I would run into concurrency problems.

SQLite wouldn't really be ACID-compliant if multiple threads were enough to defeat the Durability guarantee, would it?

That's not to say that there are no concurrency problems in SQLite, but that they're more in the way of potential bottlenecks than data corruption risks. For a reader-heavy application like yours, I suspect SQLite will perform just as well or better than your existing solution.

If you're solely after speed, I'm not sure it would be worth rewriting your app to use SQLite. This technique's value is simply in the benefit it gives when you were already going to use SQLite for some other reason. If you just want a 35% speed boost, wait a few months or buy a faster SSD. Both are going to be easier and cheaper than rewriting the data storage layer of your application.

That said, maybe there are other things in SQLite that you could use. Easy schema changes, full-text searching, more advanced indexing than the filesystem allows, etc. If you go for one of those, then the extra speed is a nice bonus.

wyoung2··on SQLite small blob storage: 35% Faster Than the Filesystem
> The same effect will be reproducible with any format storing multiple objects in a single file

Given unbounded developer time, any advantage SQLite has here can of course be matched or beaten by custom code. It's just another C library, not magic.

The real issue is, how much work will it take you to do that?

SQLite is billed as competing with `fopen()`. That's the proper way to compare it: given equal development time spent talking to the C runtime library vs. integrating SQLite, how much speed and robustness can you achieve?

> the greater potential for inconsistencies

How? In this application, SQLite is filling a role more like a filesystem than a DBMS or `fopen()` call. You can corrupt a filesystem just as easily as a DBMS. SQLite protects itself in much the same ways that good filesystems do, and it can be defeated in much the same sort of ways.

> Another is the inconvenience and duplication of effort, because all your default file-system management tools aren't available.

It's a classic tradeoff: do you need the speed this technique buys or not?

A better reason to avoid this technique is when the files you're considering storing as BLOBs need to be served by a web server that uses the `sendfile(2)` system call. There, the additional syscalls caused by the DBMS layer will probably eat up the speed advantage.

Software development is all about tradeoffs. No technique or technology is perfect for everything.

Now you know one more technique. Maybe it will be of some use to you someday.

> a pseudo-filesystem that is mapped to a single underlying file

That pretty much describes SQLite. Both SQLite and a good filesystem use tree-based structures to index data, both have ways to deal with fragmentation, both have ways to ensure consistency, both strive for durability, etc., etc.

> preferably implemented in user space to avoid overheads of multiple kernel round trips

How are you going to avoid kernel round trips when I/O is involved?

If you think user-space filesystems are fast, go try FUSE.

wyoung2··on SQLite small blob storage: 35% Faster Than the Filesystem
The article may be unclear on this point: anti-virus was turned off for these tests. What that paragraph is pointing out is that performance tanks badly (roughly a factor of 10x) when you turn on Windows Defender, and presumably even worse with other anti-virus software.

Credential: I was one of several people who vetted the article before it was published. I argued that Defender should be enabled, since it is a platform default. D. Richard Hipp chose to take the charitable path and not report those results alongside the others.

The test is easily replicated yourself. The source code for it is part of the SQLite source tree, and command lines for building and running the test are given in the article.

wyoung2··on Fossil: A decentralized version control, bug tracking, and wiki software
> Why that annoying commit hashes are so big?

In most places, Fossil shows an abbreviated form of the hash, typically 8-10 characters since Fossil, like Git, will accept any unique prefix of an artifact hash to refer to that artifact.

Here is a GitHub commit page:

  https://github.com/aioutecism/amVim-for-VSCode/commits/master
and here is a Fossil timeline page, which serves much the same purpose:

  http://fossil-scm.org/index.html/timeline
In the fossil case, the hashes are one character longer, and enclosed in square brackets instead of a roundrect.

This is a serious complaint?

> Do you really read them first?

No, you ignore them completely until you need to refer to one, and then you copy-paste it, just like with Git.

> every button and label have meaningful place and polished

Which button or label in the default Fossil skin is not in a meaningful place, and which shows a lack of polish? Be specific.

> they forgot to hire a designer.

I'm pretty sure the differences between the two stem not from forgetfulness but from the fact that GitHub, Inc. employs 608 people, is closed source, and has a revenue model, whereas Fossil is a side project of a company that's probably 1/100 that size and grows mainly by open source user code contributions.

wyoung2··on Fossil: A decentralized version control, bug tracking, and wiki software
> Cloning worked fine. I could not push/sync or auto sync over authenticated http.

That sounds like your Fossil instance allows anonymous cloning but not anonymous checkins, and that you did not give a user name with the clone command, so that when you tried to check in a change (or sync, as you say) the remote server refused to accept the anonymous contribution.

Note in my examples above the `myuser@` part.

> I found quite a few stories like this...with no resolution

The specific one you pointed me to shows exactly the problem I describe above. The URL "http://pi:8193" gives a machine name and a port, but no user name.

Fossil will use your local user name as the Fossil user in some circumstances, but not in the clone command, because that signals an anonymous clone.

wyoung2··on Fossil: A decentralized version control, bug tracking, and wiki software
> just like in SQL.

Which SQL dialect are you using where you can ROLLBACK after COMMIT? That isn't ANSI SQL-92 or SQLite behavior. Quoting the standard:

> An SQL-transaction is terminated by a <commit statement> or a <rollback statement>.

Perhaps you were thinking of savepoints?

wyoung2··on Fossil: A decentralized version control, bug tracking, and wiki software
There is about 94 kSLOC of C code in Fossil at the moment, not counting SQLite itself, according to SLOCCount. SQLite more than doubles that line count.

By that measure alone, about half of Fossil is "SQL", in the sense that more than half of the code merely manages the various DBs.

(A Fossil workspace consists of three SQLite DBs: the actual repo DB plus two machine-specific DBs, one local to the project and one global to the user login.)

There is a whole lot of embedded SQL among that C code. Simply counting the number of lines containing the 5 most common SQL statements:

SELECT: 2069 INSERT: 583 DELETE: 492 UPDATE: 410 REPLACE: 122

That doesn't mean the total number of embedded SQL statements is the total of those 5 numbers, as some of that will be compound statements using two or more of the above keywords. Fossil uses some of the most complex SQL I've ever seen outside of http://thedailywtf.com/

So, while Fossil does rely very heavily on SQL, I wouldn't say it is "written in SQL." It merely delegates as much as is sensible to SQL, in the same way that a fair bit of the Fossil web user interface uses Javascript rather than call back to the Fossil binary on the server via POST and such to fetch an updated page.

wyoung2··on Fossil: A decentralized version control, bug tracking, and wiki software
> bug in Fossil in trying to figure out what check-in to update to, followed by a user attempt to recover, ended up deleting edited/uncommitted files

Yes, uncommitted changes were lost, which is bad, but not at all what someone would think when you say "Fossil lost data."

Also, that particular problem was fixed more than five years ago.

> What other failures have there been?

I've been using Fossil for my main work repositories for over two years now, and have been monitoring the mailing list for about a year prior to that, and the only things even close to that that I can think of involve crazy user actions that confused Fossil into doing something odd, typically in the UI display only, which are now prevented at the code level.

Example: It is possible to fork the trunk by working offline — its autosync feature prevents it from happening when working online, connected to the repo you cloned from — but Fossil now demands that you heal the fork after turning autosync back on, so that you don't end up with multiple active "trunk" tips. After the trunk fork is healed, one branch becomes the "real" trunk, and the other looks like an unnamed branch that's now merged.

I'm not aware of any case of committed work being lost by Fossil. In every case where someone has managed to confuse Fossil, it's always been essentially a cosmetic issue, with all of the information necessary to get the repository back to a sane state available in the SQLite DB file.

I have personally never run into such a problem. The closest I've ever come to data loss with Fossil was purely due to ignorance.

(Briefly, Fossil UI was showing me one thing when I thought it was showing me something else, and since I didn't see what I expected to see, I thought it had lost data. This was purely a newbie misunderstanding.)

Compare git:

  https://xkcd.com/1597/
It's funny because it's truthy.
wyoung2··on Fossil: A decentralized version control, bug tracking, and wiki software
Yes, exactly this.

Not only does working on a branch sequester each developer's individual insanities until merge time, it lets other team members keep an eye on that branch so there aren't big surprises when merge time comes around. We want both aspects, not just one or the other.

Back in the early days of computing, a programming team was likely to share a single expensive computer.

Then we had the PC revolution, so each developer could have his own computer, but we kept those devs in cube farms or similar shared working spaces, and they had a LAN to coordinate their work.

Then the Internet happened, and we started doing distributed development, so we invented Subversion and mailing lists and suchlike to give team members a way to coordinate their efforts.

Then we got DVCSes, which have their uses, but they cause a new problem, which is that they let developers fork the project and go off on a tangent, completely unmonitored. When they pop up weeks or months later with a new feature, that feature may not even merge cleanly, or if it does, it may not align with the core developers' vision of where the project is going. So, the fork is never healed, and you end up with a choice of forks, no better than old-style project forks, where the dissenters just copied the project repo.

This problem was solved in the Git world by Github, which effectively turns forks into a special kind of branch, in that you can trace forks from parent repos to children, and merge child forks back in just as easily as internal branches.

Fossil solves it differently by strongly encouraging a central-and-clones model: it helps maintain team cohesion in a distributed development environment. Fossil actively fights against users going off on a tangent. This is a good thing.

You can force Fossil to work like stock Git, but its default configuration fights against that, on purpose.

wyoung2··on Fossil: A decentralized version control, bug tracking, and wiki software
> The inbuilt UI, although not polished

If your experience was more than about half a year old, you might want to look at it again. The default skin changed recently to one that is much more of a modern web UI.

It is easy to switch the skin on an existing repository or to customize it to behave the way you like. Fossil currently ships with 10 distinct skins, by my count.

wyoung2··on Fossil: A decentralized version control, bug tracking, and wiki software
I hear what you're saying, but I don't think someone evaluating Fossil should say things like, "We've always been a Bugzilla/MediaWiki/whatever shop, so we won't use tools that don't integrate with that." Instead, they should evaluate whether Fossil's version of those features provides what they need.

Specifically regarding the ticket tracker, someone evaluating Fossil should realize that it is really flexible:

  https://www.fossil-scm.org/index.html/doc/trunk/www/custom_ticket.wiki
  http://www.sqliteconcepts.org/THManual.pdf
If you don't like what Fossil's ticket system does out of the box, you can probably make it do what you need with a small amount of customization.

I don't mean to be rude or cast aspersions on you, but there's a lot of FUD like this surrounding Fossil. People look at multicolumn feature lists and see this one weird feature in one of the non-Fossil columns that has a check where Fossil doesn't and write Fossil off because they think they might need that feature. This kind of thinking is why there are so many 4x4 SUVs in the grocery store parking lot.

The simple fact is that there are a whole lot more relatively small software development teams than there are huge teams that really need a large fraction of the features in the large competing software packages.

Realize that I'm saying this about a DVCS that was designed to fit the needs of SQLite.org. If your team, code base, and community isn't larger than that of SQLite.org, it's "small" in this context, and can probably work happily within Fossil's limitations. Just as you won't be putting your Jeep Grand Cherokee in 4-Lo to get out of the parking lot, you probably don't actually need everything that, say, Bugzilla provides over Fossil's ticketing system.

Now, if you're comparing Fossil ticketing to Redmine + the Scrum dashboard plugin, and your project management is currently based on that workflow, that's a horse of a different color. But then, there's nothing preventing you from ignoring Fossil's ticketing feature and continuing to use your existing project management system.

wyoung2··on Fossil: A decentralized version control, bug tracking, and wiki software
> there are bound to be people with misconfigured clocks.

Let's step back a bit here, and realize that ticket tracking is typically one of the things you restrict access to in a Fossil repository. You're either running a private instance and have the whole repo locked down, or you're running a public instance and at least require a valid login before users are allowed to post tickets. The SQLite.org repo doesn't even allow normal users to post tickets; that feature is restricted to the core development team, with public-originating items going into the ticket tracker only after being discussed on the mailing list first.

(This policy also eliminates ticket spam.)

Therefore, the number of users that can confuse Fossil this way is small, and the Fossil server admin probably knows how to contact all of them.

Given that, the only way you're likely to confuse Fossil via this weakness is to have two people with clocks maybe a large fraction of an hour off both modifying the same ticket within an hour's span, so that the person with the bad clock appears to be making comments before the comments from other users. (Or vice versa if the clock error is in the future direction.)

So, we have an error case that can only happen among a small number of users, and only when someone isn't using NTP like they ought to, and then only when we have multiple users modifying a particular ticket in a small time window, and when it happens, it only causes a bit of web UI weirdness, not data corruption.

There's your answer, then: why spend much time fixing an extremely rare case with such minor consequences?

If it really bothers you, the Fossil project regularly accepts outside contribution patches.

> where do I go to get a list of other copies of the repository so I can query them for new bug reports?

You don't have to. Fossil syncs all artifacts back to the repo it cloned from, not just code artifacts. This includes not only tickets, but also wiki articles, etc.

The only weakness here is that Fossil's autosync feature doesn't happen on certain types of updates, including ticket changes, so you have two choices: manually say "fossil sync" to push ticket changes to the central repo, or wait until the next code commit, which will gather up the ticket changes and send those along with the code commit.

I don't know why Fossil doesn't autosync local ticket changes, but I'm sure it's purely a matter of development time and will, not a designed-in weakness. If you want remote fossils to autosync their local ticket changes, it should be easy to add the feature.

> Is there some kind of tracker that lists all the people currently publishing the same Fossil repository

In the context of your blog post, Fossil generally isn't run in the git "just fork me" mode of operation. It can run that way, but it's much more commonly used in the central-plus-clones model, where there is a canonical central repository and a working clone on each developer's machine.

This mode is encouraged by the Fossil autosync feature being turned on by default, which means each local checkin also syncs to the central repo.

You can turn autosync off, in which case Fossil works more like git, where a clone is allowed to go off on its own tangent relative to the repo it cloned from. However, that buys you many of the problems of Git relative to Fossil, such as that merging can be a pain. Autosync greatly increases the chance that any given commit will apply cleanly.

wyoung2··on Fossil: A decentralized version control, bug tracking, and wiki software
It's hard to know what your problems are from such a vague description, but I've been using Fossil over HTTP on private LANs for years now. I only use Fossil over SSH when I need to tunnel to a remote server that can't forward HTTP out to where the client can see it.

Try this:

    fossil clone http://fossil-scm.org x.fossil
Success? You just used Fossil over HTTP. :)

I have two guesses about what your problem was:

1. You didn't realize that Fossil normally listens on port 8080 by default, incrementing when it gets a bind failure, so that it could be on some higher port number, like 8082 if you have two other Fossil server instances running. If you need Fossil to bind to a specific port number, you need to pass -P to the "fossil server" command.

2. Your server machine's firewall blocks the Fossil listening port by default, and you didn't open it up.

Here's my "fossil server" wrapper script, which may help you the next time you try this:

    #!/bin/bash
    OLDPID=`pgrep fossil`
    if [ -n "$OLDPID" ]
    then
        echo "Killing old Fossil instance (PID $OLDPID) first..."
        kill $OLDPID
    
        typeset -i i=1
        while kill -0 $OLDPID > /dev/null 2>&1 && [ $i -lt 30 ]
        do
            if [ $i -eq 1 ]
            then
                echo -n "Waiting for it to die..."
            fi
            sleep '0.1s'
            i=i+1
        done
        echo
    fi
    
    fossil server -P 3691 --repolist /museum > /dev/null &
    echo Fossil server running, PID $!.
This is a Bash script, so for Windows you'd have to run it under either Cygwin or WSL.

It assumes your Fossils are stored in /museum — because where else would you keep fossils? — and that you like svnserve+1 as your Fossil port number. Adjust to taste.

To clone from such a server, say:

    fossil clone http://myuser@myserver:3691/reponame reponame.fossil
To view its web pages, visit:

    http://myserver:3691/reponame
That is, because we're serving a directory of Fossils in this case, you need to give the repository name to view a specific repository name. However, since we passed --repolist to "fossil server", if you visit the web root URL, you get a list of available repositories rather than an HTTP error.
wyoung2··on Fossil: A decentralized version control, bug tracking, and wiki software
> Does Fossil have something like 'rollback'?

Yes, but not like you mean. A commit is made using a SQLite transaction, so if any part of the commit process fails, it will roll the Fossil repo DB back to its prior state, preventing DB corruption. If you're synchronizing to a remote repository, a failure on the remote also rolls back changes to the local copy, too.

As for rolling back an already committed change, even DBMSes don't work like that. A Fossil commit is the same as SQL COMMIT: the transaction is committed now, and can't be backed out without a subsequent modification.

That said, a common way to get the effect you want with Fossil is to mark the bad commit as the start of a new branch, then resume work on the previously-damaged branch. Rather than delete history, this just pushes it off to the side, as a failed branch.

This does mean that if you make a bad commit, then make two more good commits on top of it, that moving the bad commit to an "ignored" branch will also move the two subsequent commits. However, Fossil also has a cherrypick feature that would let you apply the two good commits to the good branch.

You can sum Fossil vs Git up this way, in this regard: Git remembers what you should have done, Fossil remembers what you actually did.

wyoung2··on Show HN: BitKeeper – Enterprise-ready version control, now open-source
> I could not sit any non-technical user in front of it and have it make sense to them

So name a bug tracker with equivalent or greater flexibility to Fossil's that non-technical users do understand.

I've only used one bug tracker that's simpler than Fossil's, and that's because it had far fewer user-facing features.

Every other bug tracker I've had to use requires some training once you get past the "submit ticket" form. And a few required training even to successfully fill that out!

> Fossil's lack of any built-in emailing was also lousy.

Email is hard. Seriously hard. RFCs 821 and 822 are only the tip of an enormous iceberg. If Fossil only did the basics, it would fail for a whole lot of real-world use-cases, and it'll only get worse as email servers get tightened down more and more, to combat spam, email fraud, domain hijacking, etc.

I, too, would like Fossil to mail out commit tickets and such, but I'm not sure I want the build time for the binary and the binary size to double just because of all the protocol handlers it would need to do this properly. Keep in mind also that Fossil generally doesn't link out to third-party libraries. There are exceptions, but then, I'm not aware of a widely-available[1] full-stack SMTP library, so it would probably have to reimplement all of it internally.

Now, if you want to talk about adding a simple gateway that would allow it to interface with an external MTA, that would be different. I suspect the only thing wanting there is for someone to get around to writing the code. I don't want it bad enough to do it myself.

> "it's supposed to work that way" instead of "hey, maybe you, the user, are onto something".)

If you propose something that goes against the philosophy of Fossil, then of course the idea will be rejected. We keep seeing git users ask about various sorts of history rewriting features for example. Not gonna happen. No sense having a philosophy if a user request can change it.

If you're talking about a Fossil behavior that isn't tied to its philosophy, but it just works the way it does for some reason, logic and persuasion are a lot less effective than working code. The Fossil core developers accept patches.

----------

[1] I mean something you can expect to be in all the major package repositories, and in binary form for Windows.

wyoung2··on Show HN: BitKeeper – Enterprise-ready version control, now open-source
> I think people have a way too high tolerance for this kind of crap.

I agree.

The core problem with Git is that it was designed to serve the needs of the Linux kernel developers. Very, very, very few projects have SCM problems of similar complexity, so why do so many people try to use a tool that solves problems they don't have? Much of that internal complexity extends up into the Git interface, so you're paying for complexity you don't need.

Others in this thread have praised hg and bzr for their relative simplicity for a DVCS. I'd also like to point out Fossil.

In the normal course of daily use, Fossil as simple to use as svn.

About the only time where Fossil is more complex is the clone step before checking out a version from a remote repository.

Other than that, the daily use of Fossil is very nearly command-for-command the same as with svn. Sometimes the subcommands are different (e.g. fossil finfo instead of svn status for per-file info in the current checkout) but muscle memory works that out fairly quickly.

Most of that simplicity comes down to Fossil's autosync feature, which means that local checkout changes are automatically propagated back to the server you cloned from, so Fossil doesn't normally have separate checkin and push steps, as with Git. But if you want a 2-step commit, Fossil will let you turn off autosync.

(But you shouldn't. Local-only checkins with rare pushes is a manifestation of "the guy in the room" problem which we were warned against back in 1971 by Gerald Weinberg. Thus, Fossil fosters teamwork with better defaults than Git.)

Branching is a lot saner in Fossil than svn:

1. Fossil branches automatically include all files in a particular revision, whereas svn's branches are built on top of the per-file copy operation, so you could have a branch containing only one file. This is one of those kinds of flexibility that ends up causing problems, because you can end up with branches that don't parallel one another, making patches and merges difficult. Fossil strongly encourages you to keep related branches parallel. Automatic merges tend to succeed more often in Fossil than svn as a result.

2. Fossil has a built-in web UI with a graphical timeline, so you can see the structure of your branches. You have to install a separate GUI tool to get that with most other VCSes. The fact that you can always get a graphical view of things means that if you ever get confused about the state of a Fossil checkout tree, you'll likely spend less time confused, because you're likely also using its fully-integrated web UI.

3. Whereas svn makes you branch before you start work on a change, Fossil lets you put that off until you're ready to commit. It's at that point that you're ready to decide, "Does this change make sense on the current branch, or do I need a new one?"

Fossil's handling of branches is also a lot simpler than Git's, primarily because the local Fossil repository clone is separate from the checkout tree. Thus, it is easy to have multiple Fossil checkouts from a given local repo clone, whereas the standard Git workflow is to switch among branches in a single tree, making branch switches inexpensive.

(And yes, I'm aware that there is a way to have one local Git checkout refer to another so you can have multiple branches checked out locally without two complete repo clones. The point is that Git has yet again added unnecessary complexity to something that should be simple.)

wyoung2··on Show HN: BitKeeper – Enterprise-ready version control, now open-source
> Fossil's wiki and ticketing system are awful

Care to be more specific?

I'll grant that Fossil's wiki is not a competitor to MediaWiki, but that doesn't make it "awful." It just makes it less featureful. So, what feature do you need in a wiki that Fossil's wiki does not provide?

As for the ticketing system, again, it isn't going to replace the big boys out of the box, but it also doesn't have to match them feature-for-feature to be useful. Also, the Fossil ticketing system's behavior is not fixed: it can be modified to some extent to behave more like you need. Did you even try modifying its behavior, or are you just complaining about its out-of-the-box defaults? Be specific!

> unexpected behavior for basic commands like "fossil rm".

If you mean that you want fossil rm to also delete the checkout copy of the file in addition to removing it from the tip of the current branch, and you want fossil mv to rename the checkout copy in addition to renaming it in the repository, then you can get that by building Fossil with the --with-legacy-mv-rm flag, then setting the mv-rm-files repository option. You can enable it for all local Fossil repositories with "fossil set mv-rm-files 1".

Alternately, you can give the --hard flag to fossil mv and fossil rm. That works even with a stock binary build of Fossil.

> I'm just not super-fond of relying on Bitbucket

For some of us, relying on a cloud service just isn't an option. We're willing to give up many features in order to keep control of our private repositories.

> a package I could toss on my own VPS? I'd toss some money at that.

Fossil runs great on a VPS, even a very small one, due to its small footprint. I wrote a HOWTO for setting it up behind an nginx TLS proxy using Let's Encrypt here:

https://www.mail-archive.com/fossil-users@lists.fossil-scm.o...

wyoung2··on Fossil SCM keeps more than just your code
> let's say I want to work on an open source project done in fossil....How do I do this?

You clone the repo, open it into a working directory, and turn off autosync. Then all changes made to the repo affect only your local instance.

If you think there's a chance that you might want to send your changes back upstream, you should probably work on a branch. Then when it comes time to send your changes to someone with checkin rights on the repo you cloned from, you can use a feature that is unique to Fossil, as far as I know, called bundles. (http://fossil-scm.org/xfer/help?cmd=bundle) It is essentially a slice of the Fossil repository that someone else can integrate into their own repo, not unlike a pull request on GitHub.

I actually prefer to think of Fossil bundles as uber-patches, since they record not only the textual changes to the repo, but also file modes, the full checkin history, checkin comments, file removals and additions, etc. Basically, it fixes every weakness of patch(1).

> I don't understand where the advantage is

The advantages are listed on or linked from the front page of the Fossil web site: http://fossil-scm.org/

For me, the biggest single advantage is the simpler day-to-day working model, but maybe you will find another virtue that you prefer.

wyoung2··on Fossil SCM keeps more than just your code
> I may not own or be associated with the original repository?

Then you're doing federated development, and you should continue to use Git or another tool that supports that style of development as a first-class activity.

Many years ago, I read that > 90% of all software development is in-house private stuff. (Billing systems, custom workflow management software, etc.) A big chunk of the rest is software for sale by a company. If you have federated development going on within the bounds of a single company, you've probably also got organizational silos, which is a problem.

I suspect open source and SAAS have shifted that statistic in recent years, but I'd bet most software is still developed by a group of developers who all at least know each others' names, and can at least email each other, if not buttonhole each other at the water cooler.

Other shifts in the market, such as from boxed software on retail shelves to app stores is a net zero in this discussion, since the software is still developed the same way.

> It seems to come down to...centralized vs federated

Yes. The popularity of Git has associated "DVCS" with federated development, but one of the points I'm trying to make is that you don't have to give up on the benefits of a centralized repository if you need a DVCS.

wyoung2··on Fossil SCM keeps more than just your code
> While you shouldn't be working on multiple things, I and most other people I met, end up doing so

Fossil solves that with branches. Merging a branch into the trunk is equivalent to what Git calls pushing. The difference is that everyone can see your branch, unless you use a private branch, which is more like Git. I've argued the advantages of working on a public branch already, though, so I won't repeat that here.

That reminds me of another big difference between Fossil and Git. With Git, the checkout tree and the local repo clone are tied up in a single directory tree. The normal way to switch branches is to check all of your local changes in, then switch the current working directory over to the other branch.

While you can do that in Fossil, too, because the repository is a separate file, when working with long-lived branches, it is easier to have separate checkout trees, one for each such branch. The advantage is that switching branches doesn't change all the timestamps for changed files, invalidating build artifacts and such.

To get the same effect with Git, you have to clone the whole repo for each long-lived branch, which complicates things greatly, and wastes a bunch of disk space.

> It's not protectionist or perfectionist to keep non-working code out of the main branch

So check it in on a feature branch or a private branch. Once the new feature in the branch functions as intended, merge it into the trunk.

> why should everyone else have a non-working version of it for the duration of the rewrite?

If it's a public branch, their Fossil pulls will indeed give them a copy of your branch, but they will only be able to see your checkin comments in the Timeline view, by default. That tells your team members what you're working on, which, as I've already argued, is a good thing. If they have concerns about your direction, they can switch to your branch (a la Git) or check it out into a separate working tree. Or, they can just ignore it, and let you get about your business.

> often you _can't_ consult them

I already stated it above: if you're working on a project where you're not really collaborating with people, and where haring off in your own direction is a normal thing, then Git may well be the correct tool for you.

Fossil is for coherent projects, where people are expected to work together. The SQLite project, which Fossil was created for, is an example of this: to join the project, you have to first impress someone enough to get a commit bit, then you sign the contributor agreement. You are expected to participate on the developer mailing list once accepted.

Fossil is also good for traditional corporate development, where those with commit bits are your coworkers.

> I don't see how private branches encourage of facilitate [rewriting other people's code]

Git's normal working model is that your checkins are local first, then only optionally pushed back to the repo you cloned from. I'd bet a whole lot of the forks on GitHub will no longer integrate back into the parent project. You can see this in the language they use: forking.

This is not necessarily a bad thing. If you need federated development, Git's your tool.

But if instead you're after collaborators, contributors, and coworkers, you don't want forking the repo to be the normal first step.

> I'm not seeing why your model is inherently any better than make sure tests pass after a merge.

The "guy in the room" spends days or weeks working on code without showing anyone what he's up to. Then there is a big-bang merge event, which may or may not succeed, and may wreck his coworkers plans.

If you ignore private branches in Fossil, you end up either working on the trunk, where your coworkers will immediately see your changes, or working on a public branch, where they're likely to at least see your checkin comments, and can look at your changes if they become concerned about your direction. If you're working on a public branch, you still have the merge event, but your coworkers can't really say they're surprised when it happens, since they've been seeing your work as it progresses.

On the Fossil mailing list, you frequently see one of the core developers claiming to have finished a feature, asking for comment on their feature branch before merging it. The "guy in the room" doesn't ask for comment; he just drops his magnum opus into the trunk and says "deal with it."

> Fossil does not, your build and project environments do.

You've misunderstood my point.

Because Fossil defaults to "autosync on", you can't check in a change on a branch that has upstream changes. Fossil simply won't allow it. (There's a "force" option, but it creates a special kind of branch called a fork, which has to be resolved at some point.)

This means that if someone else changes the branch in a way that breaks the tests or whatever, Fossil strongly encourages you to pull those changes into your checkout where you can deal with it.

Git, by contrast, lets individual developers do all their checkins on a private branch, then push the whole thing to the repo they cloned from. GitHub embodies this in the pull request. There is no equivalent in Fossil, because Fossil isn't intended for federated development; it's for collaborative development.

> Nothing is stopping me but convention and what I decide to do.

This is why we have social mores and community standards of behavior. It is a good thing if the tools we use support those desirable behaviors.

← PreviousPage 5 of 6Next →