Skip to content

Commit 6b3eb33

Browse files
authored
improve update command (#163)
* update updates * update updates * update * update * update * update * update * swap to option to represent no answer * swap to option to represent no answer from isOutdated * swap to option to represent no answer from isOutdated * rename * rename * rename again
1 parent aa4ceef commit 6b3eb33

File tree

4 files changed

+66
-52
lines changed

4 files changed

+66
-52
lines changed

atlas.nimble

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Package
2-
version = "0.9.1"
2+
version = "0.9.2"
33
author = "Araq"
44
description = "Atlas is a simple package cloner tool. It manages an isolated project."
55
license = "MIT"

src/atlas.nim

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
## Simple tool to automate frequent workflows: Can "clone"
1010
## a Nimble dependency and its dependencies recursively.
1111

12-
import std / [parseopt, files, dirs, strutils, os, osproc, tables, sets, json, uri, paths]
12+
import std / [parseopt, files, dirs, strutils, os, options, osproc, tables, sets, json, uri, paths]
1313
import basic / [versions, context, osutils, configutils, reporters,
1414
nimbleparser, gitops, pkgurls, nimblecontext, compiledpatterns, packageinfos]
1515
import depgraphs, nimenv, lockfiles, confighandler, dependencies, pkgsearch
@@ -46,13 +46,13 @@ Command:
4646
install use the nimble file to setup the project's dependencies
4747
link <path> link an existing project into the current project
4848
to share its dependencies
49-
update <url|pkgname> update a package and all of its dependencies
49+
update [filter] update every dependency that matches the filter
50+
whether by name or URL. All dependencies are updated
51+
if no filter is given.
5052
search <keyA> [keyB ...]
5153
search for package that contains the given keywords
5254
extract <file.nimble> extract the requirements and custom commands from
5355
the given Nimble file
54-
updateDeps [filter] update every dependency that has a remote
55-
URL that matches `filter` if a filter is given
5656
tag [major|minor|patch]
5757
add and push a new tag, input must be one of:
5858
['major'|'minor'|'patch'] or a SemVer tag like ['1.0.3']
@@ -305,17 +305,23 @@ proc listOutdated() =
305305
for pkg in allNodes(graph):
306306
if pkg.isRoot:
307307
continue
308-
if gitops.isOutdated(pkg.ondisk):
309-
warn pkg.url.projectName, "is outdated"
308+
let res = gitops.hasNewTags(pkg.ondisk)
309+
if res.isNone:
310+
warn pkg.url.projectName, "no remote version tags found"
310311
inc updateable
311312
else:
312-
notice pkg.url.projectName, "is up to date"
313+
let (outdated, cnt) = res.get()
314+
if outdated:
315+
warn pkg.url.projectName, "is outdated; " & $cnt & " new tags available"
316+
inc updateable
317+
else:
318+
notice pkg.url.projectName, "is up to date"
313319

314320
if updateable == 0:
315321
info project(), "all packages are up to date"
316322

317-
proc updateWorkspace(filter: string) =
318-
## update the workspace
323+
proc update(filter: string) =
324+
## update the dependencies
319325
##
320326
## this will update the workspace by checking for outdated packages and
321327
## updating them if they are outdated
@@ -332,16 +338,26 @@ proc updateWorkspace(filter: string) =
332338
continue
333339

334340
let url = gitops.getRemoteUrl(pkg.ondisk)
341+
if url.len == 0:
342+
warn pkg.url.projectName, "no remote URL found; skipping..."
343+
continue
335344
if url.len == 0 or filter notin url or filter notin pkg.url.projectName:
336-
warn pkg.url.projectName, "not checking for updates"
345+
warn pkg.url.projectName, "filter not matched; skipping..."
337346
continue
338347

339-
if gitops.isOutdated(pkg.ondisk):
340-
warn pkg.url.projectName, "is outdated, updating..."
341-
gitops.updateRepo(pkg.ondisk)
348+
let res = gitops.hasNewTags(pkg.ondisk)
349+
if res.isNone:
350+
warn pkg.url.projectName, "no remote version tags found, updating origin instead"
351+
gitops.updateRepo(pkg.ondisk, onlyTags = false)
342352
needsUpdate = true
343353
else:
344-
notice pkg.url.projectName, "is up to date"
354+
let (outdated, cnt) = res.get()
355+
if outdated and cnt > 0:
356+
warn pkg.url.projectName, "outdated, updating... " & $cnt & " new tags available"
357+
gitops.updateRepo(pkg.ondisk, onlyTags = true)
358+
needsUpdate = true
359+
else:
360+
notice pkg.url.projectName, "up to date"
345361

346362
if needsUpdate:
347363
notice project(), "new dep versions available, run `atlas install` to update"
@@ -556,7 +572,7 @@ proc atlasRun*(params: seq[string]) =
556572
installDependencies(nc, nimbleFile)
557573

558574
of "update":
559-
updateWorkspace(if args.len == 0: "" else: args[0])
575+
update(if args.len == 0: "" else: args[0])
560576

561577
of "use":
562578
singleArg()

src/basic/gitops.nim

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# distribution, for details about the copyright.
77
#
88

9-
import std/[os, files, dirs, paths, osproc, sequtils, strutils, uri, sets]
9+
import std/[os, files, dirs, paths, osproc, options, sequtils, strutils, uri, sets]
1010
import reporters, osutils, versions, context
1111

1212
type
@@ -15,6 +15,7 @@ type
1515
GitRemoteUrl = "git -C $DIR config --get remote.origin.url",
1616
GitDiff = "git -C $DIR diff",
1717
GitFetch = "git -C $DIR fetch",
18+
GitFetchAll = "git -C $DIR fetch origin " & quoteShell("refs/heads/*:refs/heads/*") & " " & quoteShell("refs/tags/*:refs/tags/*"),
1819
GitTag = "git -C $DIR tag",
1920
GitTags = "git -C $DIR show-ref --tags",
2021
GitLastTaggedRef = "git -C $DIR rev-list --tags --max-count=1",
@@ -29,7 +30,7 @@ type
2930
GitLsFiles = "git -C $DIR ls-files"
3031
GitLog = "git -C $DIR log --format=%H origin/HEAD"
3132
GitLogLocal = "git -C $DIR log --format=%H HEAD"
32-
GitCurrentBranch = "git rev-parse --abbrev-ref HEAD"
33+
GitCurrentBranch = "git -C $DIR rev-parse --abbrev-ref HEAD"
3334
GitLsRemote = "git -C $DIR ls-remote --quiet --tags"
3435
GitShowFiles = "git -C $DIR show"
3536
GitListFiles = "git -C $DIR ls-tree --name-only -r"
@@ -193,9 +194,9 @@ proc shortToCommit*(path: Path, short: CommitHash): CommitHash =
193194
if vtags.len() == 1:
194195
result = vtags[0].c
195196

196-
proc expandSpecial*(path: Path, vtag: VersionTag, errorReportLevel: MsgKind = Warning, isLocalOnly = false): VersionTag =
197+
proc expandSpecial*(path: Path, vtag: VersionTag, errorReportLevel: MsgKind = Warning): VersionTag =
197198
if vtag.version.isHead():
198-
return findOriginTip(path, errorReportLevel, isLocalOnly)
199+
return findOriginTip(path, errorReportLevel, false)
199200

200201
let (cc, status) = exec(GitRevParse, path, [vtag.version.string.substr(1)], errorReportLevel)
201202

@@ -368,13 +369,6 @@ proc incrementLastTag*(path: Path, field: Natural): string =
368369
proc isShortCommitHash*(commit: string): bool {.inline.} =
369370
commit.len >= 4 and commit.len < 40
370371

371-
proc updateRepo*(path: Path) =
372-
let (outp, status) = exec(GitFetch, path, ["--tags"])
373-
if status != RES_OK:
374-
error(path, "could not update repo: " & outp)
375-
else:
376-
info(path, "successfully updated repo")
377-
378372
proc getRemoteUrl*(path: Path): string =
379373
let (cc, status) = exec(GitRemoteUrl, path, [])
380374
if status != RES_OK:
@@ -383,9 +377,10 @@ proc getRemoteUrl*(path: Path): string =
383377
else:
384378
return cc.strip()
385379

386-
proc isOutdated*(path: Path): bool =
380+
proc hasNewTags*(path: Path): Option[tuple[outdated: bool, newTags: int]] =
387381
## determine if the given git repo `f` is updateable
388-
##
382+
## returns an option tuple with the outdated flag and the number of new tags
383+
## the option is none if the repo doesn't have remote url or remote tags
389384

390385
info path, "checking is package is up to date..."
391386

@@ -394,33 +389,36 @@ proc isOutdated*(path: Path): bool =
394389

395390
let url = getRemoteUrl(path)
396391
if url.len == 0:
397-
return false
392+
return none(tuple[outdated: bool, newTags: int])
398393
let (remoteTagsList, lsStatus) = listRemoteTags(path, url)
399394
let remoteTags = remoteTagsList.toHashSet()
400395

401396
if not lsStatus:
402397
warn path, "git list remote tags failed, skipping"
403-
return false
398+
return none(tuple[outdated: bool, newTags: int])
404399

405400
if remoteTags > localTags:
406401
warn path, "got new versions:", $(remoteTags - localTags)
407-
return true
402+
return some((true, remoteTags.len() - localTags.len()))
403+
elif remoteTags.len() == 0:
404+
info path, "no local tags found, checking for new commits"
405+
return none(tuple[outdated: bool, newTags: int])
408406

409-
return false
407+
return some((false, 0))
410408

411-
proc updateDir*(path: Path, filter: string) =
412-
let (remote, _) = osproc.execCmdEx("git remote -v")
413-
if filter.len == 0 or filter in remote:
414-
let diff = checkGitDiffStatus(path)
415-
if diff.len > 0:
416-
warn($path, "has uncommitted changes; skipped")
409+
proc updateRepo*(path: Path, onlyTags = false) =
410+
## updates the repo by
411+
let url = getRemoteUrl(path)
412+
if url.len == 0:
413+
info path, "no remote URL found; cannot update"
414+
return
415+
416+
let (outp, status) =
417+
if onlyTags:
418+
exec(GitFetch, path, ["--tags", "origin"])
417419
else:
418-
let (branch, _) = exec(GitCurrentBranch, path, [])
419-
if branch.strip.len > 0:
420-
let (output, exitCode) = osproc.execCmdEx("git pull origin " & branch.strip)
421-
if exitCode != 0:
422-
error $path, output
423-
else:
424-
info($path, "successfully updated")
425-
else:
426-
error $path, "could not fetch current branch name"
420+
exec(GitFetchAll, path, [])
421+
if status != RES_OK:
422+
error(path, "could not update repo: " & outp)
423+
else:
424+
notice(path, "successfully updated repo")

tests/tgitops.nim

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import unittest
2-
import std/[os, files, dirs, paths, osproc, strutils, uri]
2+
import std/[os, files, dirs, paths, osproc, strutils, uri, options]
33
import basic/[reporters, osutils, versions, context]
44

55
import basic/gitops
@@ -123,7 +123,7 @@ suite "Git Operations Tests":
123123
discard execCmd("git commit -m \"initial commit\"")
124124
check(incrementLastTag(Path ".", 0) == "v0.0.1")
125125

126-
test "isOutdated detection":
126+
test "hasNewTags detection":
127127
withDir testDir:
128128
discard execCmd("git init")
129129
# Create initial commit and tag
@@ -138,10 +138,10 @@ suite "Git Operations Tests":
138138
discard execCmd("git commit -m \"update commit\"")
139139

140140
# Test if repo is outdated
141-
let outdated = isOutdated(Path ".")
141+
let outdated = hasNewTags(Path ".")
142142
# Note: This might fail in isolated test environments
143143
# We're mainly testing the function structure
144-
check(not outdated) # Expected to be false in test environment
144+
check(outdated.isNone) # Expected to be false in test environment
145145

146146
test "getRemoteUrl functionality":
147147
withDir testDir:

0 commit comments

Comments
 (0)