github.com/hattya/nazuna@v0.7.1-0.20240331055452-55e14c275c1c/cmd/nzn/update.go (about)

     1  //
     2  // nazuna/cmd/nzn :: update.go
     3  //
     4  //   Copyright (c) 2013-2020 Akinori Hattori <hattya@gmail.com>
     5  //
     6  //   SPDX-License-Identifier: MIT
     7  //
     8  
     9  package main
    10  
    11  import (
    12  	"fmt"
    13  	"path/filepath"
    14  	"strings"
    15  
    16  	"github.com/hattya/go.cli"
    17  	"github.com/hattya/nazuna"
    18  )
    19  
    20  func init() {
    21  	flags := cli.NewFlagSet()
    22  
    23  	app.Add(&cli.Command{
    24  		Name:  []string{"update"},
    25  		Usage: "update",
    26  		Desc: strings.TrimSpace(cli.Dedent(`
    27  			update working copy
    28  
    29  			  Update links in the working copy to match with the repository configuration.
    30  		`)),
    31  		Flags:  flags,
    32  		Action: update,
    33  		Data:   true,
    34  	})
    35  }
    36  
    37  func update(ctx *cli.Context) error {
    38  	repo := ctx.Data.(*nazuna.Repository)
    39  	wc, err := repo.WC()
    40  	if err != nil {
    41  		return err
    42  	}
    43  	ul, err := wc.MergeLayers()
    44  	if err != nil {
    45  		return wc.Errorf(err)
    46  	}
    47  
    48  	updated, removed, failed := 0, 0, 0
    49  	for _, e := range ul {
    50  		switch {
    51  		case !wc.Exists(e.Path):
    52  			continue
    53  		case !wc.IsLink(e.Path):
    54  			return fmt.Errorf("%v: not tracked", e.Path)
    55  		}
    56  		app.Println(e.Format("unlink %v -/- %v"))
    57  		switch e.Type {
    58  		case "link":
    59  			if !wc.LinksTo(e.Path, e.Origin) {
    60  				return fmt.Errorf("not linked to '%v'", e.Origin)
    61  			}
    62  		case "subrepo":
    63  			if !wc.LinksTo(e.Path, repo.SubrepoFor(e.Origin)) {
    64  				return fmt.Errorf("not linked to '%v'", e.Origin)
    65  			}
    66  		default:
    67  			var origin string
    68  			if e.Origin != "" {
    69  				origin = e.Origin
    70  			} else {
    71  				origin = e.Path
    72  			}
    73  			if !wc.LinksTo(e.Path, repo.PathFor(nil, filepath.Join(e.Layer, origin))) {
    74  				return fmt.Errorf("not linked to layer '%v'", e.Layer)
    75  			}
    76  		}
    77  		if err := wc.Unlink(e.Path); err != nil {
    78  			return err
    79  		}
    80  		removed++
    81  	}
    82  
    83  	for i := 0; i < len(wc.State.WC); i++ {
    84  		e := wc.State.WC[i]
    85  		var origin string
    86  		switch e.Type {
    87  		case "link":
    88  			origin = e.Origin
    89  		case "subrepo":
    90  			origin = repo.SubrepoFor(e.Origin)
    91  			if !nazuna.IsDir(origin) {
    92  				continue
    93  			}
    94  		default:
    95  			l, _ := repo.LayerOf(e.Layer)
    96  			if e.Origin != "" {
    97  				origin = repo.PathFor(l, e.Origin)
    98  			} else {
    99  				origin = repo.PathFor(l, e.Path)
   100  			}
   101  		}
   102  		if wc.LinksTo(e.Path, origin) {
   103  			continue
   104  		}
   105  		app.Println(e.Format("link %v --> %v"))
   106  		if err := wc.Link(origin, e.Path); err != nil {
   107  			app.Errorln("error:", wc.Errorf(err))
   108  			copy(wc.State.WC[i:], wc.State.WC[i+1:])
   109  			wc.State.WC = wc.State.WC[:len(wc.State.WC)-1]
   110  			i--
   111  			failed++
   112  		} else {
   113  			updated++
   114  		}
   115  	}
   116  
   117  	app.Printf("%d updated, %d removed, %d failed\n", updated, removed, failed)
   118  	if err := wc.Flush(); err != nil {
   119  		return err
   120  	}
   121  	if failed > 0 {
   122  		return SystemExit(1)
   123  	}
   124  	return nil
   125  }