File: modules.go

package info (click to toggle)
g10k 0.9.10-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,236 kB
  • sloc: sh: 63; makefile: 56
file content (132 lines) | stat: -rw-r--r-- 4,842 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package main

import (
	"archive/tar"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
)

func unTar(r io.Reader, targetBaseDir string) {
	funcName := funcName()
	tarBallReader := tar.NewReader(r)
	for {
		header, err := tarBallReader.Next()
		if err != nil {
			if err == io.EOF {
				break
			}
			Fatalf(funcName + "(): error while tar reader.Next() for io.Reader with targetBaseDir " + targetBaseDir + " Error: " + err.Error())
		}

		// get the individual filename and extract to the current directory
		filename := header.Name
		// check if currently extracting archive is a forge or a git module
		// we need to remove the module name from the filename otherwise the skiplist pattern would not match
		// e.g puppetlabs-stdlib-6.0.0/MAINTAINERS.md for a forge module
		// and MAINTAINERS.md for a git module
		skiplistFilename := filename
		if targetBaseDir == config.ForgeCacheDir {
			skiplistFilenameComponents := strings.SplitAfterN(filename, "/", 2)
			if len(skiplistFilenameComponents) > 1 {
				skiplistFilename = skiplistFilenameComponents[1]
			}
		}
		if matchSkiplistContent(skiplistFilename) {
			continue
		}
		targetFilename := filepath.Join(targetBaseDir, filename)

		switch header.Typeflag {
		case tar.TypeDir:
			//fmt.Println("Untarring :", targetFilename)
			// handle directory
			//fmt.Println("Creating directory :", filename)
			//err = os.MkdirAll(targetFilename, os.FileMode(header.Mode)) // or use 0755 if you prefer
			err = os.MkdirAll(targetFilename, os.FileMode(0755)) // or use 0755 if you prefer

			if err != nil {
				Fatalf(funcName + "(): error while MkdirAll() file: " + filename + " Error: " + err.Error())

			}

			err = os.Chtimes(targetFilename, header.AccessTime, header.ModTime)

			if err != nil {
				Fatalf(funcName + "(): error while Chtimes() file: " + filename + " Error: " + err.Error())

			}

		case tar.TypeReg:
			// handle normal file
			//fmt.Println("Untarring :", targetFilename)
			writer, err := os.Create(targetFilename)

			if err != nil {
				Fatalf(funcName + "(): error while Create() file: " + filename + " Error: " + err.Error())
			}
			if _, err = io.Copy(writer, tarBallReader); err != nil {
				Fatalf(funcName + "(): error while io.copy() file: " + filename + " Error: " + err.Error())
			}
			if err = os.Chmod(targetFilename, os.FileMode(header.Mode)); err != nil {
				Fatalf(funcName + "(): error while Chmod() file: " + filename + " Error: " + err.Error())
			}
			if err = os.Chtimes(targetFilename, header.AccessTime, header.ModTime); err != nil {
				Fatalf(funcName + "(): error while Chtimes() file: " + filename + " Error: " + err.Error())
			}

			writer.Close()

		case tar.TypeSymlink:
			if fileExists(targetFilename) {
				if err = os.Remove(targetFilename); err != nil {
					Fatalf(funcName + "(): error while removing existing file " + targetFilename + " to be replaced with symlink pointing to " + header.Linkname + " Error: " + err.Error())
				}
			}
			if err = os.Symlink(header.Linkname, targetFilename); err != nil {
				Fatalf(funcName + "(): error while creating symlink " + targetFilename + " pointing to " + header.Linkname + " Error: " + err.Error())
			}

		case tar.TypeLink:
			if fileExists(targetFilename) {
				if err = os.Remove(targetFilename); err != nil {
					Fatalf(funcName + "(): error while removing existing file " + targetFilename + " to be replaced with hardlink pointing to " + header.Linkname + " Error: " + err.Error())
				}
			}
			if err = os.Link(header.Linkname, targetFilename); err != nil {
				Fatalf(funcName + "(): error while creating hardlink " + targetFilename + " pointing to " + header.Linkname + " Error: " + err.Error())
			}

		// Skip pax_global_header with the commit ID this archive was created from
		case tar.TypeXGlobalHeader:
			continue

		default:
			Fatalf(funcName + "(): Unable to untar type: " + string(header.Typeflag) + " in file " + filename)
		}
	}
	// tarball produced by git archive has trailing nulls in the stream which are not
	// read by the module, when removed this can cause the git archive to hang trying
	// to output the nulls into a full pipe buffer, avoid this by discarding the rest
	// until the stream ends.
	buf := make([]byte, 4096)
	nread, err := r.Read(buf)
	for nread > 0 && err == nil {
		Debugf(fmt.Sprintf("Discarded %d bytes of trailing data from tar", nread))
		nread, err = r.Read(buf)
	}
}

func matchSkiplistContent(filePath string) bool {
	for _, blPattern := range config.PurgeSkiplist {
		filepathResult, _ := filepath.Match(blPattern, filePath)
		if strings.HasPrefix(filePath, blPattern) || filepathResult {
			Debugf("skipping file " + filePath + " because purge_skiplist pattern '" + blPattern + "' matches")
			return true
		}
	}
	//Debugf("not skipping file " + filePath + " because no purge_skiplist pattern matches")
	return false
}