github.com/nuvolaris/nuv@v0.0.0-20240511174247-a74e3a52bfd8/updates_check.go (about)

     1  // Licensed to the Apache Software Foundation (ASF) under one
     2  // or more contributor license agreements.  See the NOTICE file
     3  // distributed with this work for additional information
     4  // regarding copyright ownership.  The ASF licenses this file
     5  // to you under the Apache License, Version 2.0 (the
     6  // "License"); you may not use this file except in compliance
     7  // with the License.  You may obtain a copy of the License at
     8  //
     9  //   http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing,
    12  // software distributed under the License is distributed on an
    13  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14  // KIND, either express or implied.  See the License for the
    15  // specific language governing permissions and limitations
    16  // under the License.
    17  
    18  package main
    19  
    20  import (
    21  	"errors"
    22  	"fmt"
    23  	"io/fs"
    24  	"os"
    25  	"time"
    26  
    27  	"github.com/go-git/go-git/v5"
    28  )
    29  
    30  const LATESTCHECK = ".latestcheck"
    31  
    32  func checkUpdated(base string, timeInterval time.Duration) {
    33  	trace("checkUpdated", base)
    34  	olaris_base := joinpath(base, getNuvBranch())
    35  	latest_check_path := joinpath(olaris_base, LATESTCHECK)
    36  	olaris_path := joinpath(olaris_base, "olaris")
    37  
    38  	// if no olaris dir, no update check
    39  	if !isDir(olaris_path) {
    40  		return
    41  	}
    42  
    43  	// get info on latest_check file
    44  	file, ok := checkLatestFile(latest_check_path)
    45  	if !ok {
    46  		return
    47  	}
    48  
    49  	mtime := file.ModTime()
    50  	now := time.Now().Local()
    51  	diff := now.Sub(mtime)
    52  
    53  	if diff >= timeInterval {
    54  		fmt.Println("Checking for updates...")
    55  		// touch latest_check file ONLY if enough time has passed
    56  		touchLatestCheckFile(latest_check_path)
    57  
    58  		// check if remote olaris is newer
    59  		if checkRemoteOlarisNewer(olaris_path) {
    60  			fmt.Print("New tasks available! Use 'nuv -update' to update.\n\n")
    61  		} else {
    62  			fmt.Print("Tasks up to date!\n\n")
    63  		}
    64  	}
    65  }
    66  
    67  func checkLatestFile(path string) (fs.FileInfo, bool) {
    68  	file, err := os.Stat(path)
    69  	if errors.Is(err, os.ErrNotExist) {
    70  		debug("latestcheck file not found, skipping update check")
    71  		return nil, false
    72  	} else if err != nil {
    73  		debug("failed to access .latestcheck file info", err)
    74  		return nil, false
    75  	}
    76  
    77  	return file, true
    78  }
    79  
    80  func createLatestCheckFile(base string) {
    81  	// create latest_check file
    82  	_, err := os.Create(joinpath(base, LATESTCHECK))
    83  	if err != nil {
    84  		warn("failed to set latest_check file", err)
    85  	}
    86  }
    87  
    88  func touchLatestCheckFile(latest_check_path string) {
    89  	trace("touch latest_check file", latest_check_path)
    90  	currentTime := time.Now().Local()
    91  	err := os.Chtimes(latest_check_path, currentTime, currentTime)
    92  	if err != nil {
    93  		warn("failed to set latest update check", err)
    94  	}
    95  }
    96  
    97  func checkRemoteOlarisNewer(olaris_path string) bool {
    98  	trace("checkRemoteOlarisNewer", olaris_path)
    99  	repo, err := git.PlainOpen(olaris_path)
   100  	if err != nil {
   101  		warn("failed to check olaris folder", err)
   102  		return false
   103  	}
   104  
   105  	localRef, err := repo.Head()
   106  	if err != nil {
   107  		warn("failed to check olaris folder", err)
   108  		return false
   109  	}
   110  
   111  	remote, err := repo.Remote("origin")
   112  	if err != nil {
   113  		warn("failed to check remote olaris", err)
   114  		return false
   115  	}
   116  	_ = remote.Fetch(&git.FetchOptions{})
   117  	remoteRefs, err := remote.List(&git.ListOptions{})
   118  	if err != nil {
   119  		warn("failed to check remote olaris", err)
   120  		return false
   121  	}
   122  
   123  	// check ref is in refs
   124  	for _, remoteRef := range remoteRefs {
   125  		if localRef.Name().String() == remoteRef.Name().String() {
   126  			// is hash different?
   127  			if localRef.Hash().String() != remoteRef.Hash().String() {
   128  				return true
   129  			}
   130  		}
   131  	}
   132  	return false
   133  }