github.com/Cloud-Foundations/Dominator@v0.3.4/lib/filesystem/util/computedFiles.go (about)

     1  package util
     2  
     3  import (
     4  	"bufio"
     5  	"errors"
     6  	"fmt"
     7  	"os"
     8  	"path"
     9  	"sort"
    10  	"strings"
    11  
    12  	"github.com/Cloud-Foundations/Dominator/lib/filesystem"
    13  	"github.com/Cloud-Foundations/Dominator/lib/fsutil"
    14  	"github.com/Cloud-Foundations/Dominator/lib/json"
    15  )
    16  
    17  func spliceComputedFiles(fs *filesystem.FileSystem,
    18  	computedFileList []ComputedFile) error {
    19  	if len(computedFileList) < 1 {
    20  		return nil
    21  	}
    22  	filenameToInodeTable := fs.FilenameToInodeTable()
    23  	inodeToFilenamesTable := fs.InodeToFilenamesTable()
    24  	for _, computedFile := range computedFileList {
    25  		inum, ok := filenameToInodeTable[computedFile.Filename]
    26  		if !ok {
    27  			return errors.New(computedFile.Filename + ": missing from image")
    28  		}
    29  		if filenames, ok := inodeToFilenamesTable[inum]; !ok {
    30  			panic(computedFile.Filename + ": no corresponding list of files")
    31  		} else if len(filenames) != 1 {
    32  			return fmt.Errorf("%s: multiple inodes: %d", computedFile.Filename,
    33  				len(filenames))
    34  		}
    35  		if inode, ok :=
    36  			fs.InodeTable[inum].(*filesystem.ComputedRegularInode); ok {
    37  			inode.Source = computedFile.Source
    38  			continue
    39  		}
    40  		if oldInode, ok := fs.InodeTable[inum].(*filesystem.RegularInode); !ok {
    41  			return fmt.Errorf("%s: type: %T is not a regular inode",
    42  				computedFile.Filename, fs.InodeTable[inum])
    43  		} else {
    44  			newInode := new(filesystem.ComputedRegularInode)
    45  			newInode.Mode = oldInode.Mode
    46  			newInode.Uid = oldInode.Uid
    47  			newInode.Gid = oldInode.Gid
    48  			newInode.Source = computedFile.Source
    49  			fs.InodeTable[inum] = newInode
    50  		}
    51  	}
    52  	fs.ComputeTotalDataBytes()
    53  	clearInodePointers(&fs.DirectoryInode, "")
    54  	return fs.RebuildInodePointers()
    55  }
    56  
    57  func loadComputedFiles(filename string) ([]ComputedFile, error) {
    58  	var computedFileList []ComputedFile
    59  	if strings.HasSuffix(filename, ".json") {
    60  		file, err := os.Open(filename)
    61  		if err != nil {
    62  			return nil, err
    63  		}
    64  		defer file.Close()
    65  		reader := bufio.NewReader(file)
    66  		if err := json.Read(reader, &computedFileList); err != nil {
    67  			return nil, errors.New("error decoding computed files list " +
    68  				err.Error())
    69  		}
    70  	} else {
    71  		lines, err := fsutil.LoadLines(filename)
    72  		if err != nil {
    73  			return nil, err
    74  		}
    75  		for _, line := range lines {
    76  			fields := strings.Fields(line)
    77  			if len(fields) != 2 {
    78  				return nil, fmt.Errorf("bad line: %s", line)
    79  			}
    80  			computedFileList = append(computedFileList,
    81  				ComputedFile{fields[0], fields[1]})
    82  		}
    83  	}
    84  	return computedFileList, nil
    85  }
    86  
    87  func clearInodePointers(directoryInode *filesystem.DirectoryInode,
    88  	name string) {
    89  	for _, dirent := range directoryInode.EntryList {
    90  		if inode, ok := dirent.Inode().(*filesystem.DirectoryInode); ok {
    91  			clearInodePointers(inode, path.Join(name, dirent.Name))
    92  		}
    93  		dirent.SetInode(nil)
    94  	}
    95  }
    96  
    97  func mergeComputedFiles(base, overlay []ComputedFile) []ComputedFile {
    98  	computedFilesMap := make(map[string]string)
    99  	for _, computedFile := range base {
   100  		computedFilesMap[computedFile.Filename] = computedFile.Source
   101  	}
   102  	for _, computedFile := range overlay {
   103  		computedFilesMap[computedFile.Filename] = computedFile.Source
   104  	}
   105  	filenames := make([]string, 0, len(computedFilesMap))
   106  	for filename := range computedFilesMap {
   107  		filenames = append(filenames, filename)
   108  	}
   109  	sort.Strings(filenames)
   110  	newList := make([]ComputedFile, 0, len(computedFilesMap))
   111  	for _, filename := range filenames {
   112  		newList = append(newList, ComputedFile{
   113  			Filename: filename,
   114  			Source:   computedFilesMap[filename],
   115  		})
   116  	}
   117  	return newList
   118  }