github.com/david-imola/snapd@v0.0.0-20210611180407-2de8ddeece6d/overlord/patch/patch2.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016 Canonical Ltd 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 3 as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package patch 21 22 import ( 23 "github.com/snapcore/snapd/overlord/state" 24 "github.com/snapcore/snapd/snap" 25 ) 26 27 func init() { 28 patches[2] = []PatchFunc{patch2} 29 } 30 31 type patch2SideInfo struct { 32 RealName string `yaml:"name,omitempty" json:"name,omitempty"` 33 SnapID string `yaml:"snap-id" json:"snap-id"` 34 Revision snap.Revision `yaml:"revision" json:"revision"` 35 Channel string `yaml:"channel,omitempty" json:"channel,omitempty"` 36 DeveloperID string `yaml:"developer-id,omitempty" json:"developer-id,omitempty"` 37 Developer string `yaml:"developer,omitempty" json:"developer,omitempty"` // XXX: obsolete, will be retired after full backfilling of DeveloperID 38 EditedSummary string `yaml:"summary,omitempty" json:"summary,omitempty"` 39 EditedDescription string `yaml:"description,omitempty" json:"description,omitempty"` 40 Size int64 `yaml:"size,omitempty" json:"size,omitempty"` 41 Sha512 string `yaml:"sha512,omitempty" json:"sha512,omitempty"` 42 Private bool `yaml:"private,omitempty" json:"private,omitempty"` 43 } 44 45 type patch2DownloadInfo struct { 46 AnonDownloadURL string `json:"anon-download-url,omitempty"` 47 DownloadURL string `json:"download-url,omitempty"` 48 } 49 50 type patch2Flags int 51 52 type patch2SnapState struct { 53 SnapType string `json:"type"` // Use Type and SetType 54 Sequence []*patch2SideInfo `json:"sequence"` 55 Active bool `json:"active,omitempty"` 56 // Current indicates the current active revision if Active is 57 // true or the last active revision if Active is false 58 // (usually while a snap is being operated on or disabled) 59 Current snap.Revision `json:"current"` 60 Channel string `json:"channel,omitempty"` 61 Flags patch2Flags `json:"flags,omitempty"` 62 } 63 64 type patch2SnapSetup struct { 65 // FIXME: rename to RequestedChannel to convey the meaning better 66 Channel string `json:"channel,omitempty"` 67 UserID int `json:"user-id,omitempty"` 68 69 Flags patch2Flags `json:"flags,omitempty"` 70 71 SnapPath string `json:"snap-path,omitempty"` 72 73 DownloadInfo *patch2DownloadInfo `json:"download-info,omitempty"` 74 SideInfo *patch2SideInfo `json:"side-info,omitempty"` 75 } 76 77 func patch2SideInfoFromPatch1(oldInfo *patch1SideInfo, name string) *patch2SideInfo { 78 return &patch2SideInfo{ 79 RealName: name, // NOTE: OfficialName dropped 80 SnapID: oldInfo.SnapID, 81 Revision: oldInfo.Revision, 82 Channel: oldInfo.Channel, 83 Developer: oldInfo.Developer, // NOTE: no DeveloperID in patch1SideInfo 84 EditedSummary: oldInfo.EditedSummary, 85 EditedDescription: oldInfo.EditedDescription, 86 Size: oldInfo.Size, 87 Sha512: oldInfo.Sha512, 88 Private: oldInfo.Private, 89 } 90 } 91 92 func patch2SequenceFromPatch1(oldSeq []*patch1SideInfo, name string) []*patch2SideInfo { 93 newSeq := make([]*patch2SideInfo, len(oldSeq)) 94 for i, si := range oldSeq { 95 newSeq[i] = patch2SideInfoFromPatch1(si, name) 96 } 97 98 return newSeq 99 } 100 101 func patch2SnapStateFromPatch1(oldSnapState *patch1SnapState, name string) *patch2SnapState { 102 return &patch2SnapState{ 103 SnapType: oldSnapState.SnapType, 104 Sequence: patch2SequenceFromPatch1(oldSnapState.Sequence, name), 105 Active: oldSnapState.Active, 106 Current: oldSnapState.Current, 107 Channel: oldSnapState.Channel, 108 Flags: patch2Flags(oldSnapState.Flags), 109 } 110 } 111 112 // patch2: 113 // - migrates SnapSetup.Name to SnapSetup.SideInfo.RealName 114 // - backfills SnapState.{Sequence,Candidate}.RealName if its missing 115 func patch2(s *state.State) error { 116 117 var oldStateMap map[string]*patch1SnapState 118 err := s.Get("snaps", &oldStateMap) 119 if err == state.ErrNoState { 120 return nil 121 } 122 if err != nil { 123 return err 124 } 125 newStateMap := make(map[string]*patch2SnapState, len(oldStateMap)) 126 127 for key, oldSnapState := range oldStateMap { 128 newStateMap[key] = patch2SnapStateFromPatch1(oldSnapState, key) 129 } 130 131 // migrate SnapSetup in all tasks: 132 // - the new SnapSetup uses SideInfo, backfil from Candidate 133 // - also move SnapSetup.{Name,Revision} into SnapSetup.SideInfo.{RealName,Revision} 134 var oldSS patch1SnapSetup 135 for _, t := range s.Tasks() { 136 var newSS patch2SnapSetup 137 err := t.Get("snap-setup", &oldSS) 138 if err == state.ErrNoState { 139 continue 140 } 141 if err != nil && err != state.ErrNoState { 142 return err 143 } 144 // some things stay the same 145 newSS.Channel = oldSS.Channel 146 newSS.Flags = patch2Flags(oldSS.Flags) 147 newSS.SnapPath = oldSS.SnapPath 148 // ... and some change 149 newSS.SideInfo = &patch2SideInfo{} 150 if snapst, ok := oldStateMap[oldSS.Name]; ok && snapst.Candidate != nil { 151 newSS.SideInfo = patch2SideInfoFromPatch1(snapst.Candidate, oldSS.Name) 152 } 153 if newSS.SideInfo.RealName == "" { 154 newSS.SideInfo.RealName = oldSS.Name 155 } 156 if newSS.SideInfo.Revision.Unset() { 157 newSS.SideInfo.Revision = oldSS.Revision 158 } 159 t.Set("snap-setup", &newSS) 160 } 161 162 s.Set("snaps", newStateMap) 163 164 return nil 165 }