Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- `--lock PORT` now shows directory in success message (#77)
- New format: `Locked port 3001 for 'main' in ~/project`
- SOURCE column in `--list` output showing allocation source (free/lock/external) (#73)
- `--refresh` command to clean up stale external port allocations (#73)
- Automatic registration of busy ports as external when using `--lock <PORT>` (#73)
- When a port is already in use by another directory, it's registered as "external"
- Prevents allocation conflicts while keeping track of all busy ports
- Stores process information (PID, user, process name) for external ports
- New logging events: `ALLOC_EXTERNAL`, `ALLOC_REFRESH` (#73)

### Changed
- Smart `--force` logic for `--lock PORT` (#77)
- Free + unlocked port from another directory: allowed without `--force` (abandoned allocation)
- Free + locked port from another directory: requires `--force`
- Busy port from another directory: blocked completely (stop the service first)
- Busy unallocated port: requires `--force` (user takes responsibility)
- `--list` output now includes SOURCE column after NAME (#73)
- `--lock <PORT>` behavior when port is in use (#73)
- Same directory: port is locked for that directory
- Different directory: port is registered as external
- No longer fails when port is in use by another process

### Fixed
- Locked+busy port now correctly returned by `port-selector` (#77)
Expand Down
42 changes: 33 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,10 @@ $ port-selector --name db

# List shows NAME column
$ port-selector --list
PORT DIRECTORY NAME STATUS LOCKED USER PID PROCESS ASSIGNED
3010 ~/myproject web free - - - - 2026-01-06 20:00
3011 ~/myproject api free - - - - 2026-01-06 20:01
3012 ~/myproject db free - - - - 2026-01-06 20:02
PORT DIRECTORY NAME SOURCE STATUS LOCKED USER PID PROCESS ASSIGNED
3010 ~/myproject web free free - - - - 2026-01-06 20:00
3011 ~/myproject api free free - - - - 2026-01-06 20:01
3012 ~/myproject db free free - - - - 2026-01-06 20:02
```

The default name is `main`, which is used when `--name` is not specified:
Expand All @@ -262,11 +262,12 @@ Named allocations are useful for:
port-selector --list

# Output:
PORT DIRECTORY NAME STATUS LOCKED USER PID PROCESS ASSIGNED
3000 ~/code/merchantly/main main free yes - - - 2026-01-03 20:53
3001 ~/code/valera main free yes - - - 2026-01-03 21:08
3010 ~/myproject web free - - - - 2026-01-06 20:00
3011 ~/myproject api free - - - - 2026-01-06 20:01
PORT DIRECTORY NAME SOURCE STATUS LOCKED USER PID PROCESS ASSIGNED
3000 ~/code/merchantly/main main lock free yes - - - 2026-01-03 20:53
3001 ~/code/valera main free free yes - - - 2026-01-03 21:08
3010 ~/myproject web free free - - - - 2026-01-06 20:00
3011 ~/myproject api free free - - - - 2026-01-06 20:01
3500 ~/other-project main external busy - user 1234 python 2026-01-10 15:30
#
# Tip: Run with sudo for full process info: sudo port-selector --list

Expand All @@ -282,8 +283,20 @@ port-selector --forget --name web
# Clear all allocations
port-selector --forget-all
# Cleared 5 allocation(s)

# Refresh external port allocations (remove stale entries)
port-selector --refresh
# Refreshing 3 external allocation(s)...
# Removed 2 stale external allocation(s).
```

The **SOURCE** column indicates where the port allocation came from:
- `free` — normal allocation, currently free to use
- `lock` — port is locked for this directory
- `external` — port is used by another directory/process

External allocations are created automatically when you try to lock a port that's already in use by another directory/process. This prevents allocation conflicts while keeping track of busy ports.

### Port Locking

Lock a port to prevent it from being allocated to other directories. Useful for long-running services that should keep their port even when restarted:
Expand All @@ -303,6 +316,11 @@ cd ~/projects/new-service
port-selector --lock 3005
# Locked port 3005 for 'main'

# If port is already in use by another directory, it's registered as external
cd ~/projects/another-project
port-selector --lock 3005
# Port 3005 is externally used by python, registered as external

# Unlock port for current directory
port-selector --unlock
# Unlocked port 3000 for 'main'
Expand All @@ -318,6 +336,9 @@ port-selector --unlock 3005

When using `--lock <PORT>` with a specific port number:
- If the port is not allocated, it will be allocated to the current directory AND locked
- If the port is in use by the same directory, it will be marked as locked
- If the port is in use by another directory, it will be registered as an **external** allocation
- This prevents conflicts while keeping track of all busy ports
- This is useful when you want a specific port for a new project
- The port must be within the configured range

Expand Down Expand Up @@ -423,6 +444,7 @@ Options:
--forget --name NAME Clear port allocation for current directory with specific name
--forget-all Clear all port allocations
--scan Scan port range and record busy ports with their directories
--refresh Refresh external port allocations (remove stale entries)
--name NAME Use named allocation (default: "main")
--verbose Enable debug output (can be combined with other flags)
```
Expand Down Expand Up @@ -503,6 +525,8 @@ Logged events:
- `ALLOC_DELETE` — allocation removed (--forget)
- `ALLOC_DELETE_ALL` — all allocations removed (--forget-all)
- `ALLOC_EXPIRE` — allocation expired by TTL
- `ALLOC_EXTERNAL` — external port allocation registered
- `ALLOC_REFRESH` — external allocations refreshed

### Allocation TTL

Expand Down
42 changes: 33 additions & 9 deletions README.ru.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,10 +237,10 @@ $ port-selector --name db

# Список показывает колонку NAME
$ port-selector --list
PORT DIRECTORY NAME STATUS LOCKED USER PID PROCESS ASSIGNED
3010 ~/myproject web free - - - - 2026-01-06 20:00
3011 ~/myproject api free - - - - 2026-01-06 20:01
3012 ~/myproject db free - - - - 2026-01-06 20:02
PORT DIRECTORY NAME SOURCE STATUS LOCKED USER PID PROCESS ASSIGNED
3010 ~/myproject web free free - - - - 2026-01-06 20:00
3011 ~/myproject api free free - - - - 2026-01-06 20:01
3012 ~/myproject db free free - - - - 2026-01-06 20:02
```

Имя по умолчанию — `main`, используется когда `--name` не указан:
Expand All @@ -262,11 +262,12 @@ $ port-selector --name main # То же самое
port-selector --list

# Вывод:
PORT DIRECTORY NAME STATUS LOCKED USER PID PROCESS ASSIGNED
3000 ~/code/merchantly/main main free yes - - - 2026-01-03 20:53
3001 ~/code/valera main free yes - - - 2026-01-03 21:08
3010 ~/myproject web free - - - - 2026-01-06 20:00
3011 ~/myproject api free - - - - 2026-01-06 20:01
PORT DIRECTORY NAME SOURCE STATUS LOCKED USER PID PROCESS ASSIGNED
3000 ~/code/merchantly/main main lock free yes - - - 2026-01-03 20:53
3001 ~/code/valera main free free yes - - - 2026-01-03 21:08
3010 ~/myproject web free free - - - - 2026-01-06 20:00
3011 ~/myproject api free free - - - - 2026-01-06 20:01
3500 ~/other-project main external busy - user 1234 python 2026-01-10 15:30
#
# Совет: Запустите с sudo для полной информации о процессах: sudo port-selector --list

Expand All @@ -282,8 +283,20 @@ port-selector --forget --name web
# Удалить все аллокации
port-selector --forget-all
# Cleared 5 allocation(s)

# Обновить внешние аллокации (удалить устаревшие)
port-selector --refresh
# Refreshing 3 external allocation(s)...
# Removed 2 stale external allocation(s).
```

Колонка **SOURCE** показывает источник аллокации:
- `free` — обычная аллокация, порт сейчас свободен
- `lock` — порт заблокирован за этой директорией
- `external` — порт используется другой директорией/процессом

Внешние аллокации создаются автоматически, когда вы пытаетесь заблокировать порт, который уже занят другой директорией/процессом. Это предотвращает конфликты при выделении портов, отслеживая занятые порты.

### Блокировка портов

Заблокируйте порт, чтобы он не мог быть выделен другим директориям. Полезно для долгоживущих сервисов, которым нужно сохранять свой порт даже при перезапуске:
Expand All @@ -303,6 +316,11 @@ cd ~/projects/new-service
port-selector --lock 3005
# Locked port 3005 for 'main'

# Если порт занят другой директорией, он регистрируется как external
cd ~/projects/another-project
port-selector --lock 3005
# Port 3005 is externally used by python, registered as external

# Разблокировать порт для текущей директории
port-selector --unlock
# Unlocked port 3000 for 'main'
Expand All @@ -318,6 +336,9 @@ port-selector --unlock 3005

При использовании `--lock <PORT>` с конкретным номером порта:
- Если порт не выделен, он будет выделен текущей директории И заблокирован
- Если порт занят той же директорией, он будет помечен как заблокированный
- Если порт занят другой директорией, он будет зарегистрирован как **external** аллокация
- Это предотвращает конфликты, отслеживая все занятые порты
- Это удобно, когда вы хотите конкретный порт для нового проекта
- Порт должен находиться в настроенном диапазоне

Expand Down Expand Up @@ -423,6 +444,7 @@ Options:
--forget --name NAME Удалить аллокацию с указанным именем для текущей директории
--forget-all Удалить все аллокации
--scan Просканировать порты и записать занятые с их директориями
--refresh Обновить внешние аллокации (удалить устаревшие)
--name NAME Использовать именованную аллокацию (по умолчанию: "main")
--verbose Включить debug-вывод (можно комбинировать с другими флагами)
```
Expand Down Expand Up @@ -503,6 +525,8 @@ log: ~/.config/port-selector/port-selector.log
- `ALLOC_DELETE` — аллокация удалена (--forget)
- `ALLOC_DELETE_ALL` — все аллокации удалены (--forget-all)
- `ALLOC_EXPIRE` — аллокация истекла по TTL
- `ALLOC_EXTERNAL` — зарегистрирована внешняя аллокация порта
- `ALLOC_REFRESH` — обновлены внешние аллокации

### TTL аллокаций

Expand Down
Loading
Loading