# Обновление ccam

> ccam update заменяет ccam последним выпуском с GitHub после проверки SHA-256; --check только сообщает о выпуске, а --version устанавливает указанный тег выпуска.

Source: https://ccam.dev/ru/features/update/ · Updated 2026-10-19

`ccam update` скачивает выпуск ccam с GitHub, проверяет его по `checksums.txt` выпуска и заменяет работающий исполняемый файл одним переименованием. Используйте его, если вы установили ccam скриптом установки или из архива. ccam никогда не проверяет обновления сам: к GitHub обращается только эта команда, поэтому все остальные команды работают без сети точно так же.

## Использование

```sh
ccam update                    # install the latest release
ccam update --check            # only say whether a newer release exists
ccam update --version v0.3.0   # install that release, also an older one
ccam --dry-run update          # show what would be downloaded and replaced
```

```console
$ ccam update --check
ccam 0.5.0 is available (you have 0.4.0). Run `ccam update`.
$ ccam --dry-run update
Would update ccam 0.4.0 → 0.5.0:
  download  https://github.com/jhyunwoo/ccam/releases/download/v0.5.0/ccam_linux_amd64.tar.gz
  verify    with https://github.com/jhyunwoo/ccam/releases/download/v0.5.0/checksums.txt
  replace   /home/you/.local/bin/ccam
$ ccam update
→ downloading https://github.com/jhyunwoo/ccam/releases/download/v0.5.0/ccam_linux_amd64.tar.gz
✓ Updated ccam 0.4.0 → 0.5.0 (/home/you/.local/bin/ccam)
```

Если более нового выпуска нет, ccam выводит `ccam 0.4.0 is up to date.` и ничего не меняет. Если с `--version` указана версия, которая уже запущена, выводится `ccam 0.4.0 is already installed.`

## Параметры

| Параметр | Действие | По умолчанию |
| --- | --- | --- |
| `--check` | Только сообщить, есть ли более новый выпуск | выкл. |
| `--version <tag>` | Установить этот тег выпуска, например `v0.3.0`, новее или старше текущего | последний |
| `--dry-run` | Учитывается: находит последний тег (если `--version` не указывает другой), выполняет те же проверки исполняемого файла и выводит пути загрузки, контрольной суммы и замены, ничего не скачивая | выкл. |

`--check` и `--version` нельзя использовать вместе. Тег должен иметь вид `vMAJOR.MINOR.PATCH` с необязательным суффиксом предварительного выпуска или сборки; начальную `v` можно опустить. Всё остальное завершается ошибкой, например `--version takes a release tag such as v0.3.0, not "1.2"`.

Переменная окружения `CCAM_RELEASES_URL` заменяет `https://github.com/jhyunwoo/ccam/releases`, например для зеркала или для тестов. Структура должна быть такой же: `<url>/latest` перенаправляет на `<url>/tag/<tag>`, а файлы выпуска находятся по адресу `<url>/download/<tag>/<asset>`.

## Как это работает

Код находится в `internal/update`, который импортирует только `ccam update`. Путь запуска никогда его не вызывает.

1. `cli.updateCmd` находит работающий исполняемый файл через `os.Executable` и разрешает символические ссылки через `filepath.EvalSymlinks`. Заменяется именно этот реальный путь.
2. Без `--version` `Updater.Latest` запрашивает `<releases>/latest`, не переходя по перенаправлению, и читает тег из заголовка `Location` (`…/tag/v0.5.0`). Используется страница выпусков, а не GitHub API, поэтому ограничение API в 60 запросов в час не действует. На поиск отводится 10 секунд.
3. `parseVersion` проверяет тег по строгому шаблону. Тег попадает в адреса загрузки и в выводимую команду оболочки, поэтому ничто с `/`, `%`, пробелами или символами оболочки не проходит. `compareVersions` сравнивает его с работающей версией; предварительный выпуск считается более ранним, чем сам выпуск.
4. `managed()` и `writable()` решают, может ли ccam вообще заменить исполняемый файл (см. ниже).
5. `Updater.Fetch` одновременно скачивает `ccam_<os>_<arch>.tar.gz` и `checksums.txt`, отводя на обе загрузки 2 минуты. Каждая загрузка ограничена 256 МБ.
6. SHA-256 архива должен совпасть с его строкой в `checksums.txt`, прежде чем произойдёт что-либо ещё. Отсутствующая строка или другая контрольная сумма останавливают обновление с сообщением `nothing was changed`.
7. `extract()` читает tar и берёт первый обычный файл с именем `ccam`. Папки, ссылки и другие записи игнорируются, а исполняемый файл тоже ограничен 256 МБ.
8. `Updater.Install` записывает новый исполняемый файл через `fsutil.AtomicWrite`: временный файл `.ccam.tmp*` рядом с исполняемым файлом, с битами прав старого файла, сбрасывается на диск и переименовывается поверх старого.

Весь процесс, от поиска тега до переименования:

Архив и `checksums.txt` скачиваются параллельно, и ничего не записывается, пока контрольная сумма не совпадёт. Переименование атомарно, поэтому сбой или заполненный диск оставляют либо старый исполняемый файл, либо новый, но никогда не половину. Короткие команды, например `~/.local/bin/ccwork`, являются символическими ссылками на исполняемый файл ccam, поэтому они запускают новую версию без каких-либо изменений.

### Установка из пакета

ccam, установленный из `.deb`, принадлежит apt, и если заменить его в обход apt, база данных пакетов станет неверной. Перед загрузкой ccam проверяет, кому принадлежит исполняемый файл:

1. Исполняемый файл в `/usr/bin`, `/bin`, `/usr/sbin` или `/sbin` считается управляемым пакетным менеджером.
2. В остальных местах, если установлен `dpkg` и `dpkg -S <path>` выполняется успешно, файл тоже считается управляемым пакетным менеджером.
3. Иначе ccam создаёт и удаляет временный файл `.ccam-update-*` рядом с исполняемым файлом, чтобы убедиться, что может туда записывать.

Для исполняемого файла, управляемого пакетным менеджером, ccam останавливается и выводит шаги для apt:

```console
$ ccam update
ccam: /usr/bin/ccam was installed by a package, so `ccam update` leaves it alone.
To update the .deb, download ccam_0.5.0_linux_amd64.deb from https://github.com/jhyunwoo/ccam/releases/tag/v0.5.0 and run:
  sudo apt install ./ccam_0.5.0_linux_amd64.deb
Or install a copy in ~/.local/bin with the install script:
  curl -fsSL https://raw.githubusercontent.com/jhyunwoo/ccam/main/install.sh | sh
```

В системах, отличных от Linux, выводится только строка со скриптом установки. Если в папку нельзя записывать, ccam предлагает заново запустить скрипт установки, который устанавливает ccam в `~/.local/bin`.

## Безопасность и особые случаи

- Сборка для разработки сообщает версию `dev` и не имеет выпуска для сравнения, поэтому `ccam update` и `ccam update --check` её отклоняют. `ccam update --version vX.Y.Z` устанавливает выпуск поверх неё.
- Неудачная загрузка, отсутствующий файл для вашей платформы или несовпадение контрольной суммы оставляют установленный исполняемый файл как был.
- Несуществующий выпуск завершается ошибкой `there is no release <tag>`. Если GitHub отвечает отказом HTTP 403 или 429, ccam сообщает, что это, вероятно, ограничение частоты запросов, и предлагает повторить попытку позже.
- `--check` только читает. Он не проверяет, управляется ли исполняемый файл пакетным менеджером и доступен ли он для записи.
- `--version` с более старым тегом позволяет откатиться на предыдущую версию.

## См. также

- [Установка](https://ccam.dev/ru/docs/install.md)
- [Справочник команд](https://ccam.dev/ru/docs/commands.md)
- [Частые вопросы](https://ccam.dev/ru/docs/faq.md)
