66
77set  -euo pipefail
88
9- #  Variables from Terraform template
109EXTENSIONS=" ${EXTENSIONS} " 
1110EXTENSIONS_URLS=" ${EXTENSIONS_URLS} " 
1211EXTENSIONS_DIR=" ${EXTENSIONS_DIR} " 
1312IDE_TYPE=" ${IDE_TYPE} " 
14- 
15- #  Color constants
1613BOLD=' \033[0;1m' 
1714CODE=' \033[36;40;1m' 
1815GREEN=' \033[0;32m' 
1916YELLOW=' \033[1;33m' 
2017RED=' \033[0;31m' 
2118RESET=' \033[0m' 
2219
23- #  Check if extension is already installed
2420is_extension_installed () {
2521  local  target_dir=" $1 " 
2622  local  extension_id=" $2 " 
2723  local  extension_dir=" $target_dir /$extension_id " 
2824
29-   if  [ -d  " $extension_dir " &&  [ -f  " $extension_dir /package.json" ;  then 
30-     if  grep -q ' "name"' " $extension_dir /package.json" 2>  /dev/null;  then 
31-       if  grep -q ' "publisher"' " $extension_dir /package.json" 2>  /dev/null;  then 
25+   local  package_json=" " 
26+   if  [ -f  " $extension_dir /package.json" ;  then 
27+     package_json=" $extension_dir /package.json" 
28+   elif  [ -f  " $extension_dir /extension/package.json" ;  then 
29+     package_json=" $extension_dir /extension/package.json" 
30+   fi 
31+ 
32+   if  [ -d  " $extension_dir " &&  [ -n  " $package_json " ;  then 
33+     if  grep -q ' "name"' " $package_json " 2>  /dev/null;  then 
34+       if  grep -q ' "publisher"' " $package_json " 2>  /dev/null;  then 
3235        return  0
3336      fi 
3437    fi 
3538  fi 
3639  return  1
3740}
3841
39- #  Generate marketplace URL for extension
4042generate_extension_url () {
4143  local  extension_id=" $1 " 
4244
4345  if  [[ -z  " $extension_id " ;  then 
4446    return  1
4547  fi 
4648
47-   #  Extract publisher and extension name
4849  local  publisher
4950  publisher=$( echo " $extension_id " |  cut -d' .' ) 
5051  local  name
@@ -55,32 +56,26 @@ generate_extension_url() {
5556    return  1
5657  fi 
5758
58-   #  Generate URL based on IDE type
5959  case  " ${IDE_TYPE} " in 
6060    " vscode" " vscode-insiders" 
61-       #  Microsoft IDEs: Use the VS Code API to get metadata
6261      printf  " https://marketplace.visualstudio.com/_apis/public/gallery/vscode/%s/%s/latest" " $publisher " " $name " 
6362      ;;
6463    " vscodium" " cursor" " windsurf" " kiro" 
65-       #  Non-Microsoft IDEs: Use Open VSX Registry metadata endpoint
6664      printf  " https://open-vsx.org/api/%s/%s/latest" " $publisher " " $name " 
6765      ;;
6866    * )
69-       #  Default: Use Open VSX Registry for unknown IDEs
7067      printf  " https://open-vsx.org/api/%s/%s/latest" " $publisher " " $name " 
7168      ;;
7269  esac 
7370}
7471
75- #  Download and install extension
7672download_and_install_extension () {
7773  local  target_dir=" $1 " 
7874  local  extension_id=" $2 " 
7975  local  metadata_url=" $3 " 
8076  local  temp_dir=" $4 " 
8177  local  log_file=" $5 " 
8278
83-   #  Check if already installed (idempotency)
8479  if  is_extension_installed " $target_dir " " $extension_id " ;  then 
8580    printf  " $$ {GREEN}✓ Extension $$ {CODE}$extension_id $$ {RESET}$$ {GREEN} already installed$$ {RESET}\n" 
8681    return  0
@@ -89,57 +84,47 @@ download_and_install_extension() {
8984  printf  " $$ {BOLD}📦 Installing extension $$ {CODE}$extension_id $$ {RESET}...\n" 
9085  echo  " $( date) $extension_id " >>  " $log_file " 
9186
92-   #  Use dedicated temp directory for this extension
9387  local  extension_temp_dir
9488  extension_temp_dir=" $temp_dir /$extension_id -$( date +%s) " 
9589  local  download_file=" $temp_dir /$extension_id .vsix" 
9690
97-   #  First, get the metadata JSON
9891  echo  " $( date) $metadata_url " >>  " $log_file " 
9992  local  metadata_response
10093  if  metadata_response=$( timeout 30 curl -fsSL " $metadata_url " 2>&1 ) ;  then 
101-     #  Extract the download URL from JSON (handle both VS Code and Open VSX)
10294    local  download_url
10395    if  [[ " ${IDE_TYPE} " ==  " vscode" ||  " ${IDE_TYPE} " ==  " vscode-insiders" ;  then 
104-       #  VS Code format
10596      download_url=$( echo " $metadata_response " |  jq -r ' .versions[0].files[] | select(.assetType == "Microsoft.VisualStudio.Services.VSIXPackage") | .source' 2>  /dev/null) 
10697    else 
107-       #  Open VSX format
10898      download_url=$( echo " $metadata_response " |  jq -r ' .files.download // .downloads.universal // empty' 2>  /dev/null) 
10999    fi 
110100
111101    if  [[ -n  " $download_url " &&  " $download_url " !=  " null" ;  then 
112102      echo  " $( date) $download_url " >>  " $log_file " 
113-       #  Download the actual .vsix file
114103      echo  " $( date) $download_file " >>  " $log_file " 
115104      if  timeout 30 curl -fsSL " $download_url " " $download_file " 2>&1 ;  then 
116105        echo  " $( date) $( stat -c%s " $download_file " ) " >>  " $log_file " 
117-         #  Verify the download is a valid ZIP file
118106        echo  " $( date) " >>  " $log_file " 
119107        if  unzip -t " $download_file " >  /dev/null 2>&1 ;  then 
120-           #  Create target directory
121108          mkdir -p " $target_dir " 
122109          local  extract_dir=" $target_dir /$extension_id " 
123110
124-           #  Remove existing incomplete installation
125111          if  [ -d  " $extract_dir " ;  then 
126112            rm -rf " $extract_dir " 
127113          fi 
128114
129115          mkdir -p " $extract_dir " 
130116
131-           #  Extract extension
132117          echo  " $( date) $extract_dir " >>  " $log_file " 
133118          if  unzip -q " $download_file " " $extract_dir " 2>  /dev/null;  then 
134-             if  [ -f  " $extract_dir /package.json" ;  then 
119+             if  [ -f  " $extract_dir /package.json"   ||  [  -f   " $extract_dir /extension/package.json "  ] ;  then 
135120              printf  " $$ {GREEN}✅ Successfully installed $$ {CODE}$extension_id $$ {RESET}\n" 
136-               #  Log success
137121              echo  " $( date) $extension_id " >>  " $log_file " 
138122              rm -rf " $extension_temp_dir " 
139123              return  0
140124            else 
141125              printf  " $$ {RED}❌ Invalid extension package$$ {RESET}\n" 
142-               echo  " $( date) $extension_id " >>  " $log_file " 
126+               echo  " $( date) $extension_id  - package.json not found" >>  " $log_file " 
127+               echo  " $( date) $( ls -la " $extract_dir " ) " >>  " $log_file " 
143128              rm -rf " $extract_dir " 
144129              rm -rf " $extension_temp_dir " 
145130              return  1
@@ -181,7 +166,6 @@ download_and_install_extension() {
181166  fi 
182167}
183168
184- #  Install extension from URL
185169install_extension_from_url () {
186170  local  url=" $1 " 
187171  local  target_dir=" $2 " 
@@ -200,19 +184,16 @@ install_extension_from_url() {
200184    return  0
201185  fi 
202186
203-   #  Use dedicated temp directory
204187  local  extension_temp_dir
205188  extension_temp_dir=" $temp_dir /$extension_id -$( date +%s) " 
206189  local  download_file=" $temp_dir /$extension_id .vsix" 
207190
208191  echo  " $( date) $download_file " >>  " $log_file " 
209192  if  timeout 30 curl -fsSL " $url " " $download_file " 2>&1 ;  then 
210193    echo  " $( date) $( stat -c%s " $download_file " ) " >>  " $log_file " 
211-     #  Create target directory
212194    mkdir -p " $target_dir " 
213195    local  extract_dir=" $target_dir /$extension_id " 
214196
215-     #  Remove existing incomplete installation
216197    if  [ -d  " $extract_dir " ;  then 
217198      rm -rf " $extract_dir " 
218199    fi 
@@ -221,14 +202,15 @@ install_extension_from_url() {
221202
222203    echo  " $( date) $extract_dir " >>  " $log_file " 
223204    if  unzip -q " $download_file " " $extract_dir " 2>  /dev/null;  then 
224-       if  [ -f  " $extract_dir /package.json" ;  then 
205+       if  [ -f  " $extract_dir /package.json"   ||  [  -f   " $extract_dir /extension/package.json "  ] ;  then 
225206        printf  " $$ {GREEN}✅ Successfully installed $$ {CODE}$extension_id $$ {RESET}\n" 
226207        echo  " $( date) $extension_id  from URL" >>  " $log_file " 
227208        rm -rf " $extension_temp_dir " 
228209        return  0
229210      else 
230211        printf  " $$ {RED}❌ Invalid extension package$$ {RESET}\n" 
231-         echo  " $( date) $extension_id  from URL" >>  " $log_file " 
212+         echo  " $( date) $extension_id  from URL - package.json not found" >>  " $log_file " 
213+         echo  " $( date) $( ls -la " $extract_dir " ) " >>  " $log_file " 
232214        rm -rf " $extract_dir " 
233215        rm -rf " $extension_temp_dir " 
234216        return  1
@@ -248,7 +230,6 @@ install_extension_from_url() {
248230  fi 
249231}
250232
251- #  Install extensions from URLs
252233install_extensions_from_urls () {
253234  local  urls=" $1 " 
254235  local  target_dir=" $2 " 
@@ -261,17 +242,14 @@ install_extensions_from_urls() {
261242
262243  printf  " $$ {BOLD}🔗 Installing extensions from URLs...$$ {RESET}\n" 
263244
264-   #  Simple approach: replace commas with newlines and process each URL
265245  echo  " $urls " |  tr ' ,' ' \n' |  while  read  -r url;  do 
266-     #  Trim whitespace
267246    url=$( echo " $url " |  sed ' s/^[[:space:]]*//;s/[[:space:]]*$//' ) 
268247    if  [ -n  " $url " ;  then 
269248      install_extension_from_url " $url " " $target_dir " " $temp_dir " " $log_file " 
270249    fi 
271250  done 
272251}
273252
274- #  Install extensions from extension IDs
275253install_extensions_from_ids () {
276254  local  extensions=" $1 " 
277255  local  target_dir=" $2 " 
@@ -284,9 +262,7 @@ install_extensions_from_ids() {
284262
285263  printf  " $$ {BOLD}🧩 Installing extensions from extension IDs...$$ {RESET}\n" 
286264
287-   #  Simple approach: replace commas with newlines and process each extension
288265  echo  " $extensions " |  tr ' ,' ' \n' |  while  read  -r extension_id;  do 
289-     #  Trim whitespace
290266    extension_id=$( echo " $extension_id " |  sed ' s/^[[:space:]]*//;s/[[:space:]]*$//' ) 
291267    if  [ -n  " $extension_id " ;  then 
292268      local  metadata_url
@@ -301,51 +277,43 @@ install_extensions_from_ids() {
301277  done 
302278}
303279
304- #  Main execution
305280main () {
306281  printf  " $$ {BOLD}🚀 Starting extension installation for $$ {CODE}${IDE_TYPE} $$ {RESET} IDE...\n" 
307282
308-   #  Check dependencies
309283  for  cmd  in  curl unzip timeout;  do 
310284    if  !  command  -v " $cmd " >  /dev/null 2>&1 ;  then 
311285      printf  " $$ {RED}❌ Missing required command: $cmd $$ {RESET}\n" 
312286      return  1
313287    fi 
314288  done 
315289
316-   #  Create dedicated module directory structure
317290  local  module_dir=" $HOME /.vscode-desktop-core" 
318291  local  temp_dir=" $module_dir /tmp" 
319292  local  logs_dir=" $module_dir /logs" 
320293
321294  mkdir -p " $temp_dir " " $logs_dir " 
322295
323-   #  Set up logging
324296  local  log_file
325297  log_file=" $logs_dir /extension-installation-$( date +%Y%m%d-%H%M%S) " 
326298  printf  " $$ {BOLD}📝 Logging to: $$ {CODE}$log_file $$ {RESET}\n" 
327299
328-   #  Expand tilde in extensions directory path
329300  local  extensions_dir=" ${EXTENSIONS_DIR} " 
330301  if  [ " $$ {extensions_dir#\~}" !=  " $extensions_dir " ;  then 
331302    extensions_dir=" $HOME /$$ {extensions_dir#\~/}" 
332303  fi 
333304
334305  printf  " $$ {BOLD}📁 Using extensions directory: $$ {CODE}$extensions_dir $$ {RESET}\n" 
335306
336-   #  Create extensions directory
337307  mkdir -p " $extensions_dir " 
338308  if  [[ !  -w  " $extensions_dir " ;  then 
339309    printf  " $$ {RED}❌ Extensions directory is not writable: $extensions_dir $$ {RESET}\n" 
340310    return  1
341311  fi 
342312
343-   #  Install extensions from URLs (airgapped scenario)
344313  if  [ -n  " ${EXTENSIONS_URLS} " ;  then 
345314    install_extensions_from_urls " ${EXTENSIONS_URLS} " " $extensions_dir " " $temp_dir " " $log_file " 
346315  fi 
347316
348-   #  Install extensions from extension IDs (normal scenario)
349317  if  [[ -n  " ${EXTENSIONS} " ;  then 
350318    install_extensions_from_ids " ${EXTENSIONS} " " $extensions_dir " " $temp_dir " " $log_file " 
351319  fi 
@@ -355,7 +323,6 @@ main() {
355323  printf  " $$ {BOLD}📝 Log file: $$ {CODE}$log_file $$ {RESET}\n" 
356324}
357325
358- #  Script execution entry point
359326if  [[ -n  " ${EXTENSIONS} " ||  [[ -n  " ${EXTENSIONS_URLS} " ;  then 
360327  main
361328else 
0 commit comments