Skip to content

Latest commit

 

History

24 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

git-overleaf

CI Coverage

Native C CLI for git-overleaf. The current version is the initial v0.1.0 release.

  • auth: save a raw Overleaf Cookie header or import one from Firefox
  • list: list projects visible to the current cookie
  • clone: download a project snapshot into a new Git repo
  • init: bind an existing Git repo to an Overleaf project
  • status: inspect cached synchronization and recovery state
  • fetch: refresh the cached remote snapshot without touching local work
  • pull: merge the latest Overleaf snapshot into the current branch
  • push: upload committed HEAD, optionally replacing remote changes
  • reset: move the branch to the cached remote snapshot

Not implemented yet:

  • webdriver/browser authentication

Build And Test

Build and runtime dependencies:

  • C11 compiler
  • cmake
  • pkg-config
  • libcurl
  • jansson
  • sqlite3
  • git
  • unzip

Additional dependencies for building and running the tests:

  • C++17 compiler
  • GoogleTest (googletest / libgtest-dev)

Coverage additionally requires gcovr.

Install dependencies:

The commands below install the complete build-and-test toolchain. For a CLI-only build, GoogleTest and a separate C++ compiler are not required.

macOS (Homebrew):

xcode-select --install  # C/C++ compiler (Clang), if not already installed
brew install cmake pkgconf curl googletest jansson sqlite git unzip

Fedora:

sudo dnf install -y \
  gcc \
  gcc-c++ \
  make \
  cmake \
  pkgconf-pkg-config \
  libcurl-devel \
  gtest-devel \
  jansson-devel \
  sqlite-devel \
  git \
  unzip

Ubuntu:

sudo apt-get update
sudo apt-get install -y \
  build-essential \
  cmake \
  pkg-config \
  libcurl4-openssl-dev \
  libgtest-dev \
  libjansson-dev \
  libsqlite3-dev \
  git \
  unzip

Build the CLI without tests (no C++ compiler or GoogleTest required):

cmake -S . -B build \
  -DCMAKE_BUILD_TYPE=Release \
  -DBUILD_TESTING=OFF
cmake --build build

Run:

./build/git-overleaf --help

Build and run the tests (requires a C++17 compiler and GoogleTest):

cmake -S . -B build \
  -DCMAKE_BUILD_TYPE=Debug \
  -DBUILD_TESTING=ON
cmake --build build
ctest --test-dir build --output-on-failure

Coverage:

cmake -S . -B build-coverage \
  -DCMAKE_BUILD_TYPE=Debug \
  -DGIT_OVERLEAF_ENABLE_COVERAGE=ON
cmake --build build-coverage --target coverage

Usage

Save cookies:

./build/git-overleaf auth \
  --cookie 'connect.sid=...; overleaf_session=...' \
  --cookie-file ~/.git-overleaf-cookies

Import cookies from Firefox:

./build/git-overleaf auth --from-firefox

Target a self-hosted Overleaf instance:

./build/git-overleaf --url https://latex.example.edu list

Clone a project:

./build/git-overleaf clone --project-id PROJECT_ID --project-name 'Project Name'

Bind and synchronize an existing repo:

./build/git-overleaf init --project-id PROJECT_ID --repo /path/to/repo
./build/git-overleaf status --repo /path/to/repo
./build/git-overleaf fetch --repo /path/to/repo
./build/git-overleaf pull --repo /path/to/repo
./build/git-overleaf push --repo /path/to/repo

status uses only local Git refs and config, so it needs neither a cookie nor network access. It reports the relationship among the synchronization base, committed HEAD, and the last fetched remote snapshot, plus worktree and pending recovery state.

fetch downloads the current Overleaf snapshot and updates only the last-observed remote ref. It never changes HEAD, the index, the worktree, the synchronization base, or pending recovery state. fetch --force and fetch -f are accepted for Git command-line familiarity but have the same non-destructive behavior.

Like git pull, pull allows staged, unstaged, and untracked local changes when Git can merge without overwriting them. Non-overlapping changes remain in the worktree. If incoming changes would overwrite local changes, Git rejects the merge and leaves them intact; the remote snapshot is fetched, but no pending pull is recorded. Commit, stash, or move the overlapping changes and retry.

If a pull produces merge conflicts, resolve and commit them before running push. Use pull --abort to abort the active merge and clear the pending pull. Stale, uncommitted pending-pull metadata can also be cleared this way; an already committed merge must instead be pushed, updated with another pull, or discarded explicitly with reset.

Clone and init register a branchless logical remote named overleaf by default. Choose another name at creation time with --remote NAME. For a repository created by an older version, migrate it without network access:

./build/git-overleaf register-remote --repo /path/to/repo
# If a real remote named overleaf already exists:
./build/git-overleaf register-remote --remote overleaf-project \
  --repo /path/to/repo

The logical remote has no URL, push URL, branch, or refspec. Normal remotes such as origin remain ordinary Git remotes. git remote rename and git remote remove work normally, and a removed logical remote is not automatically recreated.

Reset the current branch to the last fetched snapshot without network access:

./build/git-overleaf reset --repo /path/to/repo
./build/git-overleaf reset --hard --repo /path/to/repo

Like git reset, the default mode is mixed: it moves the branch and resets the index while leaving tracked worktree content as unstaged changes. --hard also resets tracked worktree files. Both modes preserve untracked and ignored files, save the previous HEAD under refs/git-overleaf/backups/, and clear pending sync state only after the reset succeeds.

Push or force-push Overleaf from a bound repo:

./build/git-overleaf push --repo /path/to/repo
./build/git-overleaf push --force-with-lease --repo /path/to/repo
./build/git-overleaf push --force --repo /path/to/repo

Push always uploads the tree of committed HEAD; it never stages or commits worktree changes. Normal push and --force-with-lease both compare the current Overleaf content snapshot with the recorded synchronization base and reject independent remote changes. This is a content-snapshot lease, not an atomic Git ref lease. --force (or -f) replaces remote content with committed HEAD even when the snapshots have diverged.

Before uploading, push journals the remote base and exact target commit. If an upload is interrupted, another normal push resumes only when HEAD is still the target and every remote path matches either the old base or the target. Use pull to reconcile an independently changed or partially uploaded remote, or push --force to replace it intentionally. Pending state is cleared only after a completed push, successful reconciliation, abort, or reset.

Notes

The Firefox importer reads profiles.ini, copies cookies.sqlite plus any readable -wal / -shm sidecar files to a temporary directory, and imports only valid Overleaf session cookies for the configured host.

Repository metadata lives in local Git config:

  • git-overleaf.projectId
  • git-overleaf.projectName
  • git-overleaf.url
  • git-overleaf.baseRef
  • git-overleaf.remoteRef
  • git-overleaf.pendingAction
  • git-overleaf.pendingRemoteCommit
  • git-overleaf.pendingTargetCommit
  • git-overleaf.remoteFetchedAt

The logical remote uses this local-only Git config schema:

[remote "overleaf"]
    gitOverleafProjectId = PROJECT_ID
    skipFetchAll = true
    skipDefaultUpdate = true
[git-overleaf]
    remoteRef = refs/git-overleaf/remote

The reserved synchronization base is refs/git-overleaf/base; the latest successfully observed snapshot is refs/git-overleaf/remote. The internal metadata file .git-overleaf-sync.json is removed from downloaded snapshots before Git comparisons.

Security

The cookie file contains live Overleaf session credentials. auth writes it with mode 0600, but it should still stay outside Git repositories and logs.

About

native C command-line client for git-overleaf

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages