or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced.mdauth.mdconfig.mddiff.mdindex.mdobjects.mdreferences.mdremotes.mdrepository.mdstaging.md

remotes.mddocs/

0

# Remote Operations

1

2

Git remote repository operations including fetching, pushing, and remote management. Handles authentication, transfer progress, and remote reference management for distributed Git workflows.

3

4

## Capabilities

5

6

### Remote Management

7

8

Manage connections to remote repositories with support for multiple remotes and various protocols.

9

10

```python { .api }

11

class Remote:

12

@property

13

def name(self) -> str:

14

"""Remote name"""

15

16

@property

17

def url(self) -> str:

18

"""Remote URL"""

19

20

@property

21

def push_url(self) -> str:

22

"""Push URL (may differ from fetch URL)"""

23

24

@property

25

def refspecs(self) -> list[str]:

26

"""List of refspecs"""

27

28

@property

29

def fetch_refspecs(self) -> list[str]:

30

"""Fetch refspecs"""

31

32

@property

33

def push_refspecs(self) -> list[str]:

34

"""Push refspecs"""

35

36

# Remote Operations

37

def fetch(

38

self,

39

refspecs: list[str] = None,

40

message: str = None,

41

callbacks: 'RemoteCallbacks' = None,

42

prune: int = None,

43

update_fetchhead: bool = True

44

):

45

"""

46

Fetch from remote repository.

47

48

Parameters:

49

- refspecs: Refspecs to fetch (None = use remote's refspecs)

50

- message: Reflog message

51

- callbacks: Remote operation callbacks

52

- prune: Prune tracking branches (GIT_FETCH_PRUNE, GIT_FETCH_NO_PRUNE)

53

- update_fetchhead: Update FETCH_HEAD

54

"""

55

56

def push(

57

self,

58

refspecs: list[str],

59

callbacks: 'RemoteCallbacks' = None

60

):

61

"""

62

Push to remote repository.

63

64

Parameters:

65

- refspecs: Refspecs to push

66

- callbacks: Remote operation callbacks

67

"""

68

69

def upload(

70

self,

71

refspecs: list[str],

72

callbacks: 'RemoteCallbacks' = None

73

):

74

"""Upload pack to remote (push without updating refs)"""

75

76

def ls_remotes(self, callbacks: 'RemoteCallbacks' = None) -> list['RemoteHead']:

77

"""List remote references"""

78

79

def prune(self, callbacks: 'RemoteCallbacks' = None):

80

"""Prune remote tracking branches"""

81

82

def connect(self, direction: int, callbacks: 'RemoteCallbacks' = None):

83

"""Connect to remote"""

84

85

def disconnect(self):

86

"""Disconnect from remote"""

87

88

def download(self, refspecs: list[str] = None, callbacks: 'RemoteCallbacks' = None):

89

"""Download pack from remote"""

90

91

def update_tips(self, callbacks: 'RemoteCallbacks' = None, message: str = None):

92

"""Update remote tracking references"""

93

94

# Configuration

95

def add_fetch_refspec(self, refspec: str):

96

"""Add fetch refspec"""

97

98

def add_push_refspec(self, refspec: str):

99

"""Add push refspec"""

100

101

def set_url(self, url: str):

102

"""Set remote URL"""

103

104

def set_push_url(self, url: str):

105

"""Set push URL"""

106

107

# Remote Direction Constants

108

GIT_DIRECTION_FETCH: int # Fetch direction

109

GIT_DIRECTION_PUSH: int # Push direction

110

111

# Fetch Prune Constants

112

GIT_FETCH_PRUNE_UNSPECIFIED: int # Use config setting

113

GIT_FETCH_PRUNE: int # Prune tracking branches

114

GIT_FETCH_NO_PRUNE: int # Don't prune tracking branches

115

```

116

117

### Remote Collection

118

119

Manage multiple remotes in a repository.

120

121

```python { .api }

122

class RemoteCollection:

123

def create(self, name: str, url: str) -> Remote:

124

"""Create new remote"""

125

126

def delete(self, name: str):

127

"""Delete remote"""

128

129

def rename(self, name: str, new_name: str) -> list[str]:

130

"""

131

Rename remote.

132

133

Returns:

134

List of non-default refspecs that couldn't be renamed

135

"""

136

137

def set_url(self, name: str, url: str):

138

"""Set remote URL"""

139

140

def set_push_url(self, name: str, url: str):

141

"""Set remote push URL"""

142

143

def add_fetch_refspec(self, name: str, refspec: str):

144

"""Add fetch refspec to remote"""

145

146

def add_push_refspec(self, name: str, refspec: str):

147

"""Add push refspec to remote"""

148

149

def get(self, name: str) -> Remote:

150

"""Get remote by name"""

151

152

def __getitem__(self, name: str) -> Remote:

153

"""Get remote by name"""

154

155

def __contains__(self, name: str) -> bool:

156

"""Check if remote exists"""

157

158

def __iter__(self):

159

"""Iterate over remotes"""

160

161

def __len__(self) -> int:

162

"""Number of remotes"""

163

164

# Repository remote access

165

class Repository:

166

@property

167

def remotes(self) -> RemoteCollection:

168

"""Repository remotes collection"""

169

```

170

171

### Remote References

172

173

Information about references on remote repositories.

174

175

```python { .api }

176

class RemoteHead:

177

@property

178

def name(self) -> str:

179

"""Reference name"""

180

181

@property

182

def oid(self) -> Oid:

183

"""Reference target OID"""

184

185

@property

186

def local_oid(self) -> Oid:

187

"""Local OID for this reference"""

188

189

@property

190

def is_local(self) -> bool:

191

"""True if reference exists locally"""

192

193

class PushUpdate:

194

@property

195

def src_refname(self) -> str:

196

"""Source reference name"""

197

198

@property

199

def dst_refname(self) -> str:

200

"""Destination reference name"""

201

202

@property

203

def src(self) -> Oid:

204

"""Source OID"""

205

206

@property

207

def dst(self) -> Oid:

208

"""Destination OID"""

209

```

210

211

### Transfer Progress

212

213

Track progress of remote operations like fetch and push.

214

215

```python { .api }

216

class TransferProgress:

217

@property

218

def total_objects(self) -> int:

219

"""Total objects to transfer"""

220

221

@property

222

def indexed_objects(self) -> int:

223

"""Objects indexed so far"""

224

225

@property

226

def received_objects(self) -> int:

227

"""Objects received so far"""

228

229

@property

230

def local_objects(self) -> int:

231

"""Local objects"""

232

233

@property

234

def total_deltas(self) -> int:

235

"""Total deltas to process"""

236

237

@property

238

def indexed_deltas(self) -> int:

239

"""Deltas indexed so far"""

240

241

@property

242

def received_bytes(self) -> int:

243

"""Bytes received"""

244

```

245

246

### Remote Callbacks

247

248

Callback interface for handling remote operations, authentication, and progress.

249

250

```python { .api }

251

class RemoteCallbacks:

252

def credentials(

253

self,

254

url: str,

255

username_from_url: str,

256

allowed_types: int

257

):

258

"""

259

Provide credentials for authentication.

260

261

Parameters:

262

- url: Remote URL

263

- username_from_url: Username from URL

264

- allowed_types: Credential types allowed

265

266

Returns:

267

Credential object or None

268

"""

269

return None

270

271

def progress(self, stats: TransferProgress) -> bool:

272

"""

273

Report transfer progress.

274

275

Parameters:

276

- stats: Transfer progress information

277

278

Returns:

279

True to continue, False to cancel

280

"""

281

return True

282

283

def update_tips(

284

self,

285

refname: str,

286

old: Oid,

287

new: Oid

288

) -> int:

289

"""

290

Called when updating references.

291

292

Parameters:

293

- refname: Reference name

294

- old: Old OID

295

- new: New OID

296

297

Returns:

298

0 for success, non-zero for error

299

"""

300

return 0

301

302

def completion(self, completion_type: int) -> int:

303

"""

304

Called on operation completion.

305

306

Parameters:

307

- completion_type: Type of completed operation

308

309

Returns:

310

0 for success

311

"""

312

return 0

313

314

def push_update_reference(

315

self,

316

refname: str,

317

message: str

318

) -> int:

319

"""

320

Called for each push update.

321

322

Parameters:

323

- refname: Reference name

324

- message: Error message (if any)

325

326

Returns:

327

0 for success

328

"""

329

return 0

330

331

def pack_progress(

332

self,

333

stage: int,

334

current: int,

335

total: int

336

) -> int:

337

"""Report pack progress"""

338

return 0

339

340

def sideband_progress(self, string: str) -> int:

341

"""Handle sideband progress messages"""

342

return 0

343

344

def certificate_check(

345

self,

346

certificate,

347

valid: bool,

348

host: str

349

) -> bool:

350

"""

351

Check server certificate.

352

353

Returns:

354

True to accept certificate

355

"""

356

return valid

357

```

358

359

### Refspecs

360

361

Refspec objects define how references are mapped between local and remote repositories.

362

363

```python { .api }

364

class Refspec:

365

@property

366

def src(self) -> str:

367

"""Source reference pattern"""

368

369

@property

370

def dst(self) -> str:

371

"""Destination reference pattern"""

372

373

@property

374

def force(self) -> bool:

375

"""True if refspec forces update"""

376

377

@property

378

def string(self) -> str:

379

"""Refspec string representation"""

380

381

@property

382

def direction(self) -> int:

383

"""Refspec direction (fetch or push)"""

384

385

def src_matches(self, refname: str) -> bool:

386

"""Check if refname matches source pattern"""

387

388

def dst_matches(self, refname: str) -> bool:

389

"""Check if refname matches destination pattern"""

390

391

def transform(self, refname: str) -> str:

392

"""Transform refname using refspec"""

393

394

def rtransform(self, refname: str) -> str:

395

"""Reverse transform refname using refspec"""

396

```

397

398

### Usage Examples

399

400

#### Basic Remote Operations

401

402

```python

403

import pygit2

404

405

repo = pygit2.Repository('/path/to/repo')

406

407

# List remotes

408

print("Remotes:")

409

for remote in repo.remotes:

410

print(f" {remote.name}: {remote.url}")

411

412

# Add new remote

413

origin = repo.remotes.create('origin', 'https://github.com/user/repo.git')

414

415

# Get existing remote

416

origin = repo.remotes['origin']

417

print(f"Origin URL: {origin.url}")

418

419

# Set different push URL

420

origin.set_push_url('git@github.com:user/repo.git')

421

```

422

423

#### Fetching from Remote

424

425

```python

426

# Simple fetch

427

origin = repo.remotes['origin']

428

origin.fetch()

429

430

# Fetch with custom refspecs

431

origin.fetch(['refs/heads/*:refs/remotes/origin/*'])

432

433

# Fetch with callbacks

434

class FetchCallbacks(pygit2.RemoteCallbacks):

435

def progress(self, stats):

436

print(f"Received {stats.received_objects}/{stats.total_objects} objects")

437

return True

438

439

def credentials(self, url, username_from_url, allowed_types):

440

if allowed_types & pygit2.GIT_CREDENTIAL_SSH_KEY:

441

return pygit2.Keypair('git', '~/.ssh/id_rsa.pub', '~/.ssh/id_rsa', '')

442

return None

443

444

callbacks = FetchCallbacks()

445

origin.fetch(callbacks=callbacks)

446

```

447

448

#### Pushing to Remote

449

450

```python

451

# Push specific branch

452

origin.push(['refs/heads/main:refs/heads/main'])

453

454

# Push all branches

455

origin.push(['refs/heads/*:refs/heads/*'])

456

457

# Push with callbacks

458

class PushCallbacks(pygit2.RemoteCallbacks):

459

def push_update_reference(self, refname, message):

460

if message:

461

print(f"Error pushing {refname}: {message}")

462

return -1

463

else:

464

print(f"Successfully pushed {refname}")

465

return 0

466

467

def credentials(self, url, username_from_url, allowed_types):

468

return pygit2.UserPass('username', 'password')

469

470

callbacks = PushCallbacks()

471

origin.push(['refs/heads/feature:refs/heads/feature'], callbacks=callbacks)

472

```

473

474

#### Listing Remote References

475

476

```python

477

# List remote references

478

remote_refs = origin.ls_remotes()

479

print("Remote references:")

480

for ref in remote_refs:

481

print(f" {ref.name}: {ref.oid}")

482

if ref.is_local:

483

print(f" (local: {ref.local_oid})")

484

```

485

486

#### Advanced Remote Operations

487

488

```python

489

# Clone with custom callbacks

490

class CloneCallbacks(pygit2.RemoteCallbacks):

491

def progress(self, stats):

492

if stats.total_objects > 0:

493

percent = (stats.received_objects * 100) // stats.total_objects

494

print(f"Cloning: {percent}% ({stats.received_objects}/{stats.total_objects})")

495

return True

496

497

def credentials(self, url, username_from_url, allowed_types):

498

if 'github.com' in url:

499

if allowed_types & pygit2.GIT_CREDENTIAL_SSH_KEY:

500

return pygit2.Keypair('git', '~/.ssh/id_rsa.pub', '~/.ssh/id_rsa', '')

501

return None

502

503

callbacks = CloneCallbacks()

504

repo = pygit2.clone_repository(

505

'git@github.com:user/repo.git',

506

'/local/path',

507

callbacks=callbacks

508

)

509

510

# Prune remote tracking branches

511

origin.prune()

512

513

# Update remote URL

514

repo.remotes.set_url('origin', 'https://new-url.com/repo.git')

515

516

# Add additional fetch refspec

517

origin.add_fetch_refspec('refs/pull/*/head:refs/remotes/origin/pr/*')

518

```

519

520

#### Working with Refspecs

521

522

```python

523

# Examine refspecs

524

for refspec_str in origin.fetch_refspecs:

525

refspec = pygit2.Refspec(refspec_str)

526

print(f"Refspec: {refspec.string}")

527

print(f" Source: {refspec.src}")

528

print(f" Destination: {refspec.dst}")

529

print(f" Force: {refspec.force}")

530

531

# Test refspec matching

532

if refspec.src_matches('refs/heads/main'):

533

transformed = refspec.transform('refs/heads/main')

534

print(f" 'refs/heads/main' -> '{transformed}'")

535

536

# Add custom refspecs

537

origin.add_fetch_refspec('refs/tags/*:refs/tags/*')

538

origin.add_push_refspec('refs/heads/main:refs/heads/master')

539

```

540

541

#### Authentication Examples

542

543

```python

544

# SSH key authentication

545

class SSHCallbacks(pygit2.RemoteCallbacks):

546

def credentials(self, url, username_from_url, allowed_types):

547

if allowed_types & pygit2.GIT_CREDENTIAL_SSH_KEY:

548

return pygit2.Keypair(

549

'git',

550

'/home/user/.ssh/id_rsa.pub',

551

'/home/user/.ssh/id_rsa',

552

'passphrase'

553

)

554

return None

555

556

# Username/password authentication

557

class HTTPSCallbacks(pygit2.RemoteCallbacks):

558

def credentials(self, url, username_from_url, allowed_types):

559

if allowed_types & pygit2.GIT_CREDENTIAL_USERPASS_PLAINTEXT:

560

return pygit2.UserPass('username', 'personal_access_token')

561

return None

562

563

# SSH agent authentication

564

class AgentCallbacks(pygit2.RemoteCallbacks):

565

def credentials(self, url, username_from_url, allowed_types):

566

if allowed_types & pygit2.GIT_CREDENTIAL_SSH_KEY:

567

return pygit2.KeypairFromAgent('git')

568

return None

569

```

570

571

#### Progress Monitoring

572

573

```python

574

class DetailedCallbacks(pygit2.RemoteCallbacks):

575

def __init__(self):

576

self.total_bytes = 0

577

self.start_time = time.time()

578

579

def progress(self, stats):

580

# Calculate transfer rate

581

elapsed = time.time() - self.start_time

582

if elapsed > 0:

583

rate = stats.received_bytes / elapsed / 1024 # KB/s

584

else:

585

rate = 0

586

587

print(f"\rObjects: {stats.received_objects}/{stats.total_objects} "

588

f"Deltas: {stats.indexed_deltas}/{stats.total_deltas} "

589

f"Rate: {rate:.1f} KB/s", end='')

590

591

return True

592

593

def sideband_progress(self, string):

594

print(f"Remote: {string.strip()}")

595

return 0

596

597

callbacks = DetailedCallbacks()

598

origin.fetch(callbacks=callbacks)

599

print() # New line after progress

600

```