# overleaf-ce-sync [English](README.md) Sincronización bidireccional «al estilo git» para **Overleaf Community Edition autoalojado**. La integración nativa con Git (`git-bridge`) es una función de Server Pro y no se puede usar con CE: la Snapshot API y el servidor OAuth2 que necesita están en módulos de código cerrado. Esta herramienta ofrece lo más parecido: bajar un proyecto al disco, versionarlo con tu propio `git` y subir los cambios. Usa los mismos endpoints HTTP que la interfaz web. El login por HTTP simple, que en overleaf.com no funciona por el CAPTCHA, anda bien en CE porque CE no tiene CAPTCHA. ## Instalación Con [pipx](https://pipx.pypa.io) (entorno aislado, `overleaf-ce-sync` en el PATH): ```bash git clone https://git.all.ar/pub/overleaf-ce-sync.git cd overleaf-ce-sync pipx install -e . # -e = editable: los cambios al código se aplican sin reinstalar ``` La única dependencia es `requests`; hace falta Python 3.8 o posterior. Si pipx avisa que `~/.local/bin` no está en el PATH, ejecutá `pipx ensurepath` y abrí otra terminal. ## Uso ```bash # 1. iniciar sesión una vez por servidor (la cookie se guarda en ~/.config/overleaf-ce, con permisos 0600) overleaf-ce-sync login --host overleaf.example.com --email vos@example.com # 2. buscar el id del proyecto overleaf-ce-sync list # 3. clonarlo en un repo git overleaf-ce-sync clone milibro cd milibro # 4. ciclo normal overleaf-ce-sync pull # trae los cambios remotos (pisa los locales) # ...editar, git commit... overleaf-ce-sync push # sube los archivos cambiados localmente ``` Después del primer `pull`/`clone`, el servidor y el id del proyecto quedan guardados en `.overleaf-ce.json`, así que dentro del directorio alcanza con `overleaf-ce-sync pull` / `overleaf-ce-sync push`. ## Cómo funciona La sincronización se ancla en **commits de git**: `push` publica solo lo que commiteaste, nunca las ediciones sueltas del árbol de trabajo. - **pull** → `GET /Project//download/zip`, lo extrae sobre el árbol de trabajo, hace un «commit de sincronización» y lo recuerda como `last_sync_commit` en `.overleaf-ce.json`. - **push** → sube el estado **commiteado** (HEAD). Compara `last_sync_commit..HEAD`, sube el contenido *commiteado* de cada archivo cambiado (`git show HEAD:`) con `POST /Project//upload` (pisa por nombre) y avanza `last_sync_commit` a HEAD. Lo no commiteado se ignora. - El endpoint de subida necesita el **id de la carpeta raíz** del proyecto. Se obtiene una sola vez por socket.io con **xhr-polling** (HTTP simple: funciona detrás de cualquier proxy inverso, sin upgrade a websocket) a partir del evento `joinProjectResponse`, y se guarda en `.overleaf-ce.json`. ## Limitaciones - **push solo manda cambios commiteados.** Editá, hacé `git commit` y después `push`. Un archivo con cambios sin commitear se saltea (y te avisa). - **Los borrados no se propagan.** Los archivos que borrás en tus commits se informan pero NO se borran en Overleaf (por seguridad). Borralos desde la web; usá `pull --prune` para reflejar en tu copia los borrados remotos. - **pull pisa el árbol de trabajo** y se niega si hay cambios sin commitear (`--force` para forzarlo). Commitea solo lo que trae, así que tu historial intercala commits «overleaf pull» con los tuyos. - **Binario o documento**: lo decide Overleaf por archivo; volver a subir crea versiones nuevas en su historial, por eso push solo manda los archivos cuyo contenido commiteado cambió. - No cierres sesión en el navegador con la que iniciaste: Overleaf puede revocar la cookie. ## Alternativa: id de la carpeta raíz sin socket.io Si la detección por xhr-polling falla con tu instalación, sacá el id una vez de Mongo en el servidor y pasalo con `--root-folder-id` (después queda guardado): ```bash docker compose exec mongo mongosh sharelatex --quiet --eval \ 'printjson(db.projects.findOne({_id:ObjectId("")},{ "rootFolder._id":1}))' overleaf-ce-sync push --root-folder-id ``` ## Licencia MIT