Goodbye R-Forge, hello Codeberg

[This article was first published on Achim Zeileis, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

After 20 years of service the R-Forge package hosting platform will be retiring soon. Codeberg is a modern alternative that shares many of the ideas and values that R-Forge was built on. A tutorial for transitioning to Codeberg (or other Git-based platforms) is provided.

You say goodbye

R-Forge was created 20 years ago after the 2nd useR! conference in 2006. Kurt Hornik had the idea that “R should have its own SourceForge!” (note that GitHub did not yet exist at the time). However, the goal was that this code sharing platform should be created by the R community for the R community. The implementation was led by Stefan Theussl in the following months using GForge/FusionForge, a fork of the software behind SourceForge. Hosting and funding was provided by WU Wirtschaftsuniversität Wien and The R Project.

R-Forge offers a Subversion (SVN) repository for collaborative development of R packages along with various other services that were state of the art at the time: daily package builds and checks, forums, mailing lists, bug trackers, web pages. A short introduction was published in the inaugural issue of The R Journal: Theußl & Zeileis (2009). “Collaborative Software Development Using R-Forge.” The R Journal, 1(1):9-14. doi:10.32614/RJ-2009-007

As the FusionForge system is no longer maintained, R-Forge will be retired in the next months, switching to a read-only site. The system was somewhat dated anyways: The website has a certain “00s” vibe (see the screenshot of my profile page below) and it lacks services that became standard over the last two decades like issues, pull requests, and continuous integration.

Screenshot of Achim Zeileis' user page on R-Forge

I say hello

Codeberg is a non-profit, community-led effort that provides services to free and open-source projects, such as Git hosting (using Forgejo), pages, continuous integration, etc. It is run by the non-profit organization Codeberg e.V. based in Berlin, Germany, which contributors can (but do not have to) become a member of. (I joined this summer.)

Thus, Codeberg shares many of the ideas and values, that R-Forge was built on, but provides state-of-the-art open-source tools for collaborative development of R packages (and beyond). For a first impression of the look and feel, see the screenshot of my profile page below.

Screenshot of Achim Zeileis' user page on Codeberg

I say go go go

For transitioning from R-Forge to Codeberg – or some other Git-based code hosting platform – Reto Stauffer has written up a step-by-step guide. The most important steps are also listed below.

1. SVN checkout from R-Forge

The starting point for the transition is the SVN repository from R-Forge that you probably have already checked out. For illustration we are using the c403 R package that is one of the packages contained in the exams project on R-Forge.

svn checkout svn://R-Forge.R-project.org/svnroot/exams/

2. List of R-Forge contributors

To find all SVN usernames who ever contributed to the SVN on R-Forge repository (in this example, to the folder exams/pkg/c403) the command svn log -q can be used. Using the following shell command a text file with the unique names can be created. Note that exams/pkg/c403 needs to be replaced for other projects and the output file name can be adjusted too:

(cd exams/pkg/c403 && svn log -q | grep -e '^r' | awk 'BEGIN { FS = "|" } ; { print $2 }' | sort | uniq) > \
  authors_c403.txt

This creates the text file authors_c403.txt which will look something like:

  azeileis
  retos

This file needs to be modified by adding the full names and e-mail addresses of the contributors. Important: The leading spaces need to be removed in each line for the subsequent commands to work.

azeileis = Achim Zeileis <[email protected]>
retos = Reto Stauffer <[email protected]>

Provided the profile pages on R-Forge are up to date for the users, it is also possible to scrape this information, see the optional step 2*. below.

3. Clone a Git version of the SVN

Using git-svn a Git version of the SVN can be easily created. For this step it is crucial that all users are listed in the authors file created in the previous step, otherwise git-svn will fail.

git svn clone svn://R-Forge.R-project.org/svnroot/exams/pkg/c403 \
    --authors-file=authors_c403.txt --no-metadata \
    git-c403

Again, adjust the URL of the SVN, the authors file name, and the name of the git repository (git-c403) as needed.

4. Optional: Filter files in the Git repository

This step is not needed for the c403 example but is particularly useful when migrating a full R-Forge repository (rather than just a pkg sub-folder). In that case it might be useful to filter out certain files or directories such as the initial README file auto-created by R-Forge or the www sub-directory (typically just containing original PHP file or a auto-generated web page from pkgdown or altdoc).

Such files can be filtered, i.e., erased completely from the repository history, using git-filter-repo:

git-filter-repo --force --path 'README' --invert-paths
git-filter-repo --force --path 'www' --invert-paths

5. Import Git repository on Codeberg

First, create a new project on Codeberg, e.g., https://codeberg.org/zeileis/c403. The project should be completely empty without any initial commit.

Then, all left to do then is to tell the Git repository where its new home is (again adjust all names correspondingly):

cd git-c403
git remote add origin ssh://[email protected]/zeileis/c403.git
git push --set-upstream origin main

Analogous commands can be used for setting the origin to a project on GitHub, GitLab, etc.

All history will be immediately available in the new repository. If the authors have accounts on Codeberg, their profiles will be linked based on the e-mail address(es) associated with their Codeberg account.

6. Package builds and checks via R-universe

To automatically build and check the development versions of the R package on Codeberg, the most convenient solution is to use the R-universe service developed by Jeroen Ooms and provided by rOpenSci.

In short, to make use of it, you need a GitHub account and create a repository like zeileis.r-universe.dev. This should contain a packages.json file with the names and repository URLs of one or more R packages, e.g.,

[
    {
        "package": "c403",
        "url": "https://codeberg.org/zeileis/c403"
    }
]

As a final step, the R-universe app has to be installed on the same GitHub account. See the R-universe set up documentation for more details.

7. Codeberg pages

If you want to add a project page for your package, e.g., generated via altdoc or pkgdown, then https://codeberg.page/ can be used.

The c403 package does not have a page, yet, but for an example see https://zeileis.codeberg.page/topmodels/ which is generated from the topmodels R package using altdoc in combination with quarto.

All that needs to be done to create the page manually, is to create an empty branch pages via git switch --orphan pages, adding the static site files, and pushing them to the repository.

Alternatively, it is also possible to use Forgejo actions to do this automatically.

Finally, inform users where the sources of the package can be found, i.e., update the DESCRIPTION (especially the URL and BugReports fields) and in the NEWS. Additionally, a README.md file would be expected in a project while on R-Forge this was often not used (because R-Forge would be aware of the DESCRIPTION instead). Finally, it is recommended to add a link from the old R-Forge project to the new Codeberg project (possibly also in the www folder). To assure that none of the contributors can make modifications in the old R-Forge SVN, the permissions on R-Forge can be switched to read-only (typically for the Senior Developer role).

Optional addition: 2.* Scrape author names and e-mail addresses

In step 2, after the file with the author names (authors_c403.txt in the example above) has been created, one can try to automate the addition of proper names and e-mail addresses. This is particularly useful if there are more than just a handful of users. It works when the R-Forge user pages list the proper names and the (current) e-mail addresses.

The function below can be called in R as

rforge_authors("c403")

It first reads the authors_c403.txt file, looks up all users on R-Forge (using the rvest package), and then updates the authors_c403.txt file accordingly.

rforge_authors <- function(x) {
  txt <- sprintf("authors_%s.txt", x)
  if (file.exists(txt)) {
    a <- readLines(txt)
    a <- gsub(" ", "", a)
  } else {
    stop(sprintf("Please use 'svn log' to set up an '%s' file with all user names", txt))
  }

  for (i in seq_along(a)) {  
    doc <- a[i] |>
      sprintf(fmt = "https://r-forge.r-project.org/users/%s/") |>
      rvest::read_html()
    n <- doc |>
      rvest::html_table() |>
      lapply(as.data.frame) |>
      lapply(subset, subset = X1 == "Real Name:", select = "X2", drop = TRUE) |>
      unlist() |>
      unique()
    if (length(n) < 1L) n <- "FIXME"
    e <- doc |>
      rvest::html_table() |>
      lapply(as.data.frame) |>
      lapply(subset, subset = X1 == "Email Address:", select = "X2", drop = TRUE) |>
      unlist() |>
      unique() |>
      gsub(pattern = " @nospam@ ", replacement = "@", fixed = TRUE)
    if (length(e) < 1L) e <- "FIXME"
    a[i] <- sprintf("%s = %s <%s>", a[i], n, e)
  }
  writeLines(a, txt)
  invisible(a)
}
To leave a comment for the author, please follow the link and comment on their blog: Achim Zeileis.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)