# Working with repositories on rbd.svn.bd

This server stores project files in Subversion (SVN) repositories. You upload a project
by committing it, and download it by checking it out. Everything below works from a
terminal, a CI job, or an automated agent — there is nothing to click.

> Every request needs a Subversion account. There is no anonymous access, including for
> reading. If you do not have a username and password yet, ask an administrator to create
> one and to grant your account access to the repository you need.

## Endpoints

| What | URL |
|---|---|
| A repository | `https://rbd.svn.bd/svn/<repo>` |
| The same URL in a browser | shows a file browser, history and diffs |
| Change your own password | [https://rbd.svn.bd/user/](https://rbd.svn.bd/user/) |
| Management console (administrators) | [https://rbd.svn.bd/](https://rbd.svn.bd/) |
| This guide, as plain Markdown | [https://rbd.svn.bd/doc.md](https://rbd.svn.bd/doc.md) |

Replace `<repo>` with the repository name throughout. Repository names contain letters,
digits, `.`, `_` and `-`.

## Before you start

You need the `svn` command-line client. On Debian or Ubuntu:

```bash
sudo apt-get install -y subversion
```

Check that your account can reach the repository. This is the one command worth running
first, because it distinguishes "wrong password" from "no permission" from "no such
repository":

```bash
svn info https://rbd.svn.bd/svn/<repo> \
  --username <user> --password <pass> \
  --non-interactive --no-auth-cache
```

Exit status `0` means the repository exists and you may read it. Anything else is
explained under [When something fails](#when-something-fails).

### Flags to use in scripts

| Flag | Why |
|---|---|
| `--non-interactive` | never prompt; fail with a message instead of hanging |
| `--no-auth-cache` | do not write the password into `~/.subversion` |
| `--username` / `--password` | supply the credential explicitly |
| `--trust-server-cert` | only if the TLS certificate is not trusted on your machine |

To keep the password out of your shell history and out of `ps`, use svn 1.10 or newer and
pass it on standard input instead:

```bash
printf '%s' "$SVN_PASSWORD" | svn --password-from-stdin --username "$SVN_USER" \
  --non-interactive --no-auth-cache info https://rbd.svn.bd/svn/<repo>
```

## Download a project

### A working copy you can edit and commit back

```bash
svn checkout https://rbd.svn.bd/svn/<repo> my-project \
  --username <user> --password <pass> --non-interactive --no-auth-cache
cd my-project
```

This is what you want almost always. It brings down every file and remembers where it
came from, so `svn commit` later sends your changes back.

### Just the files, with no version-control metadata

```bash
svn export https://rbd.svn.bd/svn/<repo> my-project \
  --username <user> --password <pass> --non-interactive --no-auth-cache
```

`export` omits the `.svn` directory. Use it for a build or a release artefact — you
cannot commit from an exported directory.

### An older version, or a single file

```bash
# the project as it stood at revision 42
svn checkout -r 42 https://rbd.svn.bd/svn/<repo> my-project-r42

# print one file to standard output, without downloading the project
svn cat https://rbd.svn.bd/svn/<repo>/trunk/README.md
```

## Upload a project

### Into an empty repository

`svn import` copies a directory into the repository in one commit. It is the fastest way
to get an existing project in, and it leaves your directory untouched — nothing becomes a
working copy.

```bash
svn import ./my-project https://rbd.svn.bd/svn/<repo> \
  -m "Initial import" \
  --username <user> --password <pass> --non-interactive --no-auth-cache
```

If the repository was created with the standard layout, import into `trunk` instead so
branches and tags stay usable:

```bash
svn import ./my-project https://rbd.svn.bd/svn/<repo>/trunk -m "Initial import" \
  --username <user> --password <pass> --non-interactive --no-auth-cache
```

After importing, check the project out to keep working on it:

```bash
svn checkout https://rbd.svn.bd/svn/<repo> my-project-wc \
  --username <user> --password <pass> --non-interactive --no-auth-cache
```

### Connecting a folder you already have to a repository

Use this when the files must stay exactly where they are — an existing project directory
you are already working in. `--force` lets a checkout land in a directory that is not
empty; your files are kept, and the repository's files are merged alongside them.

```bash
cd /path/to/my-project

# 1. tie this directory to the repository
svn checkout https://rbd.svn.bd/svn/<repo> . --force \
  --username <user> --password <pass> --non-interactive --no-auth-cache

# 2. schedule everything that is not yet versioned
svn add --force . --quiet

# 3. send it
svn commit -m "Initial import of my-project" \
  --username <user> --password <pass> --non-interactive --no-auth-cache
```

From then on the directory is a working copy: `svn status`, `svn commit` and `svn update`
all work in place.

### Sending later changes

```bash
svn status                  # what changed
svn add --force . --quiet   # pick up new files
svn commit -m "What I changed" \
  --username <user> --password <pass> --non-interactive --no-auth-cache
```

`svn commit` sends every modified file in the working copy. Name a path to send only part
of it: `svn commit src/ -m "..."`.

### Leave build output out

Committing `node_modules`, `bin`, `obj` or `.venv` wastes the storage limit and slows
every checkout. Mark them ignored once:

```bash
svn propset svn:ignore "node_modules
bin
obj
.venv
*.log" .
svn commit -m "Ignore build output" \
  --username <user> --password <pass> --non-interactive --no-auth-cache
```

## Everyday commands

| Task | Command |
|---|---|
| See what changed locally | `svn status` |
| Pull the latest changes | `svn update` |
| Add new files | `svn add --force . --quiet` |
| Delete a file | `svn rm path/to/file` |
| Send your changes | `svn commit -m "message"` |
| Read the history | `svn log --limit 20` |
| See a change | `svn diff -c 42` |
| Throw away local edits | `svn revert -R .` |
| Where did this copy come from | `svn info` |

## Storage limits

Each administrator has a storage limit that covers every repository they own, together
with every repository owned by the repository managers under them. A commit that would
push the total past the limit is refused **before anything is written** — the repository
is left exactly as it was.

A refused commit looks like this:

```text
svn: E165001: Commit blocked by pre-commit hook (exit code 1) with output:

Commit refused — storage quota exceeded.

  administrator : admin
  quota         : 30.0 GB
  already used  : 30.0 GB
  this commit   : 42.1 MB

Nothing was written. Remove data, or ask for a higher limit.
```

There is nothing to retry. Either remove data from the repositories, or ask an
administrator to raise the limit. Large binaries and build output are the usual cause;
see [Leave build output out](#upload-a-project).

## When something fails

| Message | What it means | What to do |
|---|---|---|
| `E170001` · authorization failed | The username or password is wrong | Check them, or set a new password at [https://rbd.svn.bd/user/](https://rbd.svn.bd/user/) |
| `403 Forbidden` · access denied | The account is valid but has no rule for that path | Ask an administrator to grant read or read-write on the repository |
| `E170013` · URL doesn't exist | Wrong repository name, or it has not been created | Check the name; ask an administrator to create it |
| `E165001` · storage quota exceeded | The owning administrator is out of space | Remove data or ask for a higher limit |
| `E155007` · not a working copy | The command was run outside a checked-out directory | `cd` into the working copy, or check out first |
| `E155004` · locked working copy | A previous command was interrupted | `svn cleanup` |
| `E160013` · path not found | The file or folder does not exist at that revision | Check the path and the revision |

## For automated agents

This section is the short, deterministic version. Every command is non-interactive and
reports success through its exit status.

Set these once:

```bash
SVN_URL="https://rbd.svn.bd/svn/<repo>"
SVN_USER="<user>"
SVN_PASS="<pass>"
SVN_OPTS="--non-interactive --no-auth-cache --username $SVN_USER --password $SVN_PASS"
```

**Step 1 — confirm the repository is reachable.** Stop here if this fails; nothing later
will work, and the error text says which of the three causes it is.

```bash
svn info "$SVN_URL" $SVN_OPTS || exit 1
```

**Step 2 — find out whether it is empty.** No output means an empty repository, so
`import` is the right upload path; output means use the checkout path instead.

```bash
svn ls "$SVN_URL" $SVN_OPTS
```

**Step 3a — upload every file, empty repository.**

```bash
svn import ./my-project "$SVN_URL" -m "Initial import" $SVN_OPTS
```

**Step 3b — upload every file, repository already has content, or the local folder must
stay in place.**

```bash
cd ./my-project
svn checkout "$SVN_URL" . --force $SVN_OPTS
svn add --force . --quiet
svn commit -m "Import" $SVN_OPTS
```

**Step 4 — download every file.**

```bash
svn checkout "$SVN_URL" ./my-project $SVN_OPTS   # editable, can commit back
svn export   "$SVN_URL" ./my-project $SVN_OPTS   # plain files only
```

**Step 5 — confirm what landed.**

```bash
svn info "$SVN_URL" $SVN_OPTS | grep "Last Changed Rev"
```

### Rules worth encoding

- Never retry a commit that failed with `storage quota exceeded`. It is a limit, not a
  transient error, and retrying cannot succeed.
- Retry once, after a pause, on a network error (`E730054`, `E170013` with "Unable to
  connect"). Do not retry an authentication or authorization failure.
- Run `svn add --force . --quiet` before every commit if new files may have appeared;
  `svn commit` alone will not send files that were never added.
- Exclude `node_modules`, `bin`, `obj`, `.venv`, `dist`, `target` and log files before
  the first import. Storage is capped, and history is permanent — data committed once
  keeps costing space even after it is deleted in a later revision.
- One project per repository. Do not put several unrelated projects in one repository.

## Machine-readable copies

| File | Contents |
|---|---|
| [https://rbd.svn.bd/doc.md](https://rbd.svn.bd/doc.md) | This page, as Markdown |
| [https://rbd.svn.bd/llms.txt](https://rbd.svn.bd/llms.txt) | A short pointer file for language models |
| [https://rbd.svn.bd/robots.txt](https://rbd.svn.bd/robots.txt) | Crawling rules |

This page and `/doc.md` are public and require no credentials. Everything else on the
server does.