@@ -5,7 +5,9 @@ import { spawnSync } from 'node:child_process'
55const args = new Set ( process . argv . slice ( 2 ) )
66const skipBuild = args . has ( '--skip-build' )
77const allowDirty = args . has ( '--allow-dirty' )
8+ const forceMain = args . has ( '--main' )
89const cwd = process . cwd ( )
10+ const RELEASE_TAG_RE = / ^ v \d + \. \d + \. \d + ( [ - . + ] [ 0 - 9 A - Z a - z . - ] + ) ? $ /
911
1012function log ( message ) {
1113 process . stdout . write ( `[update] ${ message } \n` )
@@ -45,6 +47,13 @@ function runOrThrow(command, commandArgs, options = {}) {
4547 }
4648}
4749
50+ function getLatestStableTag ( ) {
51+ const tagList = run ( 'git' , [ 'tag' , '--list' , 'v*' , '--sort=-v:refname' ] )
52+ if ( ! tagList . ok ) return null
53+ const tags = tagList . out . split ( '\n' ) . map ( ( line ) => line . trim ( ) ) . filter ( Boolean )
54+ return tags . find ( ( tag ) => RELEASE_TAG_RE . test ( tag ) ) || null
55+ }
56+
4857function main ( ) {
4958 const gitCheck = run ( 'git' , [ 'rev-parse' , '--is-inside-work-tree' ] )
5059 if ( ! gitCheck . ok ) {
@@ -68,17 +77,40 @@ function main() {
6877 fail ( 'Could not resolve current git SHA.' )
6978 }
7079
71- runOrThrow ( 'git' , [ 'fetch' , 'origin' , 'main' , '--quiet' ] )
72- const behind = run ( 'git' , [ 'rev-list' , 'HEAD..origin/main' , '--count' ] )
73- const behindBy = Number . parseInt ( behind . out || '0' , 10 ) || 0
80+ runOrThrow ( 'git' , [ 'fetch' , '--tags' , 'origin' , '--quiet' ] )
7481
75- if ( behindBy <= 0 ) {
76- log ( 'Already up to date. Nothing to install.' )
77- return
78- }
82+ let updateSource = 'main'
83+ let pullOutput = ''
84+ const latestTag = forceMain ? null : getLatestStableTag ( )
85+
86+ if ( latestTag ) {
87+ const behind = run ( 'git' , [ 'rev-list' , `HEAD..${ latestTag } ^{commit}` , '--count' ] )
88+ const behindBy = Number . parseInt ( behind . out || '0' , 10 ) || 0
89+
90+ if ( behindBy <= 0 ) {
91+ log ( `Already on latest stable release (${ latestTag } ) or newer.` )
92+ return
93+ }
7994
80- log ( `Found ${ behindBy } new commit(s). Updating now...` )
81- runOrThrow ( 'git' , [ 'pull' , '--ff-only' , 'origin' , 'main' ] )
95+ updateSource = `stable release ${ latestTag } `
96+ log ( `Found ${ behindBy } commit(s) behind ${ latestTag } . Updating now...` )
97+ runOrThrow ( 'git' , [ 'checkout' , '-B' , 'stable' , `${ latestTag } ^{commit}` ] )
98+ pullOutput = `Updated to ${ latestTag } `
99+ } else {
100+ runOrThrow ( 'git' , [ 'fetch' , 'origin' , 'main' , '--quiet' ] )
101+ const behind = run ( 'git' , [ 'rev-list' , 'HEAD..origin/main' , '--count' ] )
102+ const behindBy = Number . parseInt ( behind . out || '0' , 10 ) || 0
103+
104+ if ( behindBy <= 0 ) {
105+ log ( 'Already up to date. Nothing to install.' )
106+ return
107+ }
108+
109+ updateSource = 'main branch'
110+ log ( `Found ${ behindBy } new commit(s) on origin/main. Updating now...` )
111+ runOrThrow ( 'git' , [ 'pull' , '--ff-only' , 'origin' , 'main' ] )
112+ pullOutput = `Pulled origin/main (+${ behindBy } )`
113+ }
82114
83115 const changed = run ( 'git' , [ 'diff' , '--name-only' , `${ beforeSha . out } ..HEAD` ] )
84116 const changedFiles = new Set ( ( changed . out || '' ) . split ( '\n' ) . map ( ( s ) => s . trim ( ) ) . filter ( Boolean ) )
@@ -97,6 +129,7 @@ function main() {
97129 }
98130
99131 log ( 'Update complete.' )
132+ log ( `Source: ${ updateSource } . ${ pullOutput } ` . trim ( ) )
100133 log ( 'Restart SwarmClaw to apply the new version.' )
101134}
102135
0 commit comments