github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/doltcore/env/actions/docs.go (about) 1 // Copyright 2020 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package actions 16 17 import ( 18 "context" 19 "errors" 20 21 "github.com/dolthub/dolt/go/libraries/doltcore/doltdocs" 22 23 "github.com/dolthub/dolt/go/libraries/doltcore/diff" 24 "github.com/dolthub/dolt/go/libraries/doltcore/doltdb" 25 "github.com/dolthub/dolt/go/libraries/doltcore/env" 26 ) 27 28 // SaveTrackedDocsFromWorking saves docs from the working root to the filesystem, and doesn't modify untracked docs. 29 func SaveTrackedDocsFromWorking(ctx context.Context, dEnv *env.DoltEnv) error { 30 localDocs := dEnv.Docs 31 workingRoot, err := dEnv.WorkingRoot(ctx) 32 if err != nil { 33 return err 34 } 35 36 return SaveTrackedDocs(ctx, dEnv.DocsReadWriter(), workingRoot, workingRoot, localDocs) 37 } 38 39 // SaveDocsFromWorking saves docs from the working root to the filesystem, and could overwrite untracked docs. 40 func SaveDocsFromWorking(ctx context.Context, dEnv *env.DoltEnv) error { 41 workingRoot, err := dEnv.WorkingRoot(ctx) 42 if err != nil { 43 return err 44 } 45 46 return SaveDocsFromRoot(ctx, workingRoot, dEnv) 47 } 48 49 // SaveDocsFromRoot saves docs from the root given to the filesystem, and could overwrite untracked docs. 50 func SaveDocsFromRoot(ctx context.Context, root *doltdb.RootValue, dEnv *env.DoltEnv) error { 51 localDocs := dEnv.Docs 52 drw := dEnv.DocsReadWriter() 53 54 docs, err := doltdocs.GetDocsFromRoot(ctx, root, doltdocs.GetDocNamesFromDocs(doltdocs.SupportedDocs)...) 55 if err != nil { 56 return err 57 } 58 59 err = drw.WriteDocsToDisk(docs) 60 if err != nil { 61 // If we can't update docs on disk, attempt to revert the change 62 drw.WriteDocsToDisk(localDocs) 63 return err 64 } 65 66 return nil 67 } 68 69 // SaveTrackedDocs writes the docs from the targetRoot to the filesystem. The working root is used to identify untracked docs, which are left unchanged. 70 func SaveTrackedDocs(ctx context.Context, drw env.DocsReadWriter, workRoot, targetRoot *doltdb.RootValue, localDocs doltdocs.Docs) error { 71 docDiffs, err := diff.NewDocDiffs(ctx, workRoot, nil, localDocs) 72 if err != nil { 73 return err 74 } 75 76 docs := removeUntrackedDocs(localDocs, docDiffs) 77 78 docs, err = doltdocs.GetDocsFromRoot(ctx, targetRoot, doltdocs.GetDocNamesFromDocs(docs)...) 79 if err != nil { 80 return err 81 } 82 83 err = drw.WriteDocsToDisk(docs) 84 85 if err != nil { 86 // If we can't update docs on disk, attempt to revert the change 87 _ = drw.WriteDocsToDisk(localDocs) 88 return err 89 } 90 91 return nil 92 } 93 94 func docIsUntracked(doc string, untracked []string) bool { 95 for _, val := range untracked { 96 if doc == val { 97 return true 98 } 99 } 100 return false 101 } 102 103 func removeUntrackedDocs(docs doltdocs.Docs, docDiffs *diff.DocDiffs) doltdocs.Docs { 104 result := doltdocs.Docs{} 105 untracked := getUntrackedDocs(docs, docDiffs) 106 107 for _, doc := range docs { 108 if !docIsUntracked(doc.DocPk, untracked) { 109 result = append(result, doc) 110 } 111 } 112 return result 113 } 114 115 func getUntrackedDocs(docs doltdocs.Docs, docDiffs *diff.DocDiffs) []string { 116 untracked := []string{} 117 for _, docName := range docDiffs.Docs { 118 dt := docDiffs.DocToType[docName] 119 if dt == diff.AddedDoc { 120 untracked = append(untracked, docName) 121 } 122 } 123 124 return untracked 125 } 126 127 func getUpdatedWorkingAndStagedWithDocs(ctx context.Context, working, staged, head *doltdb.RootValue, docs doltdocs.Docs) (currRoot, stgRoot *doltdb.RootValue, retDocs doltdocs.Docs, err error) { 128 root := head 129 _, ok, err := staged.GetTable(ctx, doltdb.DocTableName) 130 if err != nil { 131 return nil, nil, nil, err 132 } else if ok { 133 root = staged 134 } 135 136 docs, err = doltdocs.GetDocsFromRoot(ctx, root, doltdocs.GetDocNamesFromDocs(docs)...) 137 if err != nil { 138 return nil, nil, nil, err 139 } 140 141 currRoot, err = doltdocs.UpdateRootWithDocs(ctx, working, docs) 142 if err != nil { 143 return nil, nil, nil, err 144 } 145 146 stgRoot, err = doltdocs.UpdateRootWithDocs(ctx, staged, docs) 147 if err != nil { 148 return nil, nil, nil, err 149 } 150 151 return currRoot, stgRoot, docs, nil 152 } 153 154 // GetUnstagedDocs retrieves the unstaged docs (docs from the filesystem). 155 func GetUnstagedDocs(ctx context.Context, dbData env.DbData) (doltdocs.Docs, error) { 156 _, unstagedDocDiffs, err := diff.GetDocDiffs(ctx, dbData.Ddb, dbData.Rsr, dbData.Drw) 157 if err != nil { 158 return nil, err 159 } 160 unstagedDocs := doltdocs.Docs{} 161 for _, docName := range unstagedDocDiffs.Docs { 162 docAr, err := dbData.Drw.GetDocsOnDisk(docName) 163 if err != nil { 164 return nil, err 165 } 166 if len(docAr) < 1 { 167 return nil, errors.New("error: Failed getting unstaged docs") 168 } 169 170 unstagedDocs = append(unstagedDocs, docAr[0]) 171 } 172 return unstagedDocs, nil 173 } 174 175 // SaveDocsFromWorkingExcludingFSChanges saves docs from the working root to the filesystem, and does not overwrite changes to docs on the FS. 176 // Intended to be called after checking that no conflicts exist (during a checkout or merge, i.e.). 177 func SaveDocsFromWorkingExcludingFSChanges(ctx context.Context, dEnv *env.DoltEnv, docsToExclude doltdocs.Docs) error { 178 workingRoot, err := dEnv.WorkingRoot(ctx) 179 if err != nil { 180 return err 181 } 182 183 var docsToSave doltdocs.Docs 184 if len(docsToExclude) > 0 { 185 for _, doc := range dEnv.Docs { 186 for _, excludedDoc := range docsToExclude { 187 if doc.DocPk != excludedDoc.DocPk { 188 docsToSave = append(docsToSave, doc) 189 } 190 } 191 } 192 } else { 193 docsToSave = dEnv.Docs 194 } 195 196 return SaveTrackedDocs(ctx, dEnv.DocsReadWriter(), workingRoot, workingRoot, docsToSave) 197 } 198 199 // GetTablesOrDocs takes a slice of table or file names. Table names are returned as given. Supported doc names are 200 // read from disk and their name replace with the names of the dolt_docs system table in the input slice. Supported docs 201 // are returned in the second return param. 202 func GetTablesOrDocs(drw env.DocsReadWriter, tablesOrFiles []string) (tables []string, docs doltdocs.Docs, err error) { 203 for i, tbl := range tablesOrFiles { 204 if _, ok := doltdocs.IsSupportedDoc(tbl); ok { 205 docAr, err := drw.GetDocsOnDisk(tbl) 206 if err != nil { 207 return nil, nil, err 208 } 209 if len(docAr) < 1 { 210 return nil, nil, errors.New("error: Failed getting docs") 211 } 212 213 doc := docAr[0] 214 if doc.DocPk == "" { 215 return nil, nil, errors.New("Supported doc not found on disk.") 216 } 217 docs = append(docs, doc) 218 tablesOrFiles[i] = doltdb.DocTableName 219 } 220 } 221 return tablesOrFiles, docs, nil 222 }