patman: Show the current directory in GetInputFilename()
[oweals/u-boot.git] / tools / patman / tools.py
1 # SPDX-License-Identifier: GPL-2.0+
2 #
3 # Copyright (c) 2016 Google, Inc
4 #
5
6 import command
7 import os
8 import shutil
9 import tempfile
10
11 import tout
12
13 # Output directly (generally this is temporary)
14 outdir = None
15
16 # True to keep the output directory around after exiting
17 preserve_outdir = False
18
19 # Path to the Chrome OS chroot, if we know it
20 chroot_path = None
21
22 # Search paths to use for Filename(), used to find files
23 search_paths = []
24
25
26 def PrepareOutputDir(dirname, preserve=False):
27     """Select an output directory, ensuring it exists.
28
29     This either creates a temporary directory or checks that the one supplied
30     by the user is valid. For a temporary directory, it makes a note to
31     remove it later if required.
32
33     Args:
34         dirname: a string, name of the output directory to use to store
35                 intermediate and output files. If is None - create a temporary
36                 directory.
37         preserve: a Boolean. If outdir above is None and preserve is False, the
38                 created temporary directory will be destroyed on exit.
39
40     Raises:
41         OSError: If it cannot create the output directory.
42     """
43     global outdir, preserve_outdir
44
45     preserve_outdir = dirname or preserve
46     if dirname:
47         outdir = dirname
48         if not os.path.isdir(outdir):
49             try:
50                 os.makedirs(outdir)
51             except OSError as err:
52                 raise CmdError("Cannot make output directory '%s': '%s'" %
53                                 (outdir, err.strerror))
54         tout.Debug("Using output directory '%s'" % outdir)
55     else:
56         outdir = tempfile.mkdtemp(prefix='binman.')
57         tout.Debug("Using temporary directory '%s'" % outdir)
58
59 def _RemoveOutputDir():
60     global outdir
61
62     shutil.rmtree(outdir)
63     tout.Debug("Deleted temporary directory '%s'" % outdir)
64     outdir = None
65
66 def FinaliseOutputDir():
67     global outdir, preserve_outdir
68
69     """Tidy up: delete output directory if temporary and not preserved."""
70     if outdir and not preserve_outdir:
71         _RemoveOutputDir()
72
73 def GetOutputFilename(fname):
74     """Return a filename within the output directory.
75
76     Args:
77         fname: Filename to use for new file
78
79     Returns:
80         The full path of the filename, within the output directory
81     """
82     return os.path.join(outdir, fname)
83
84 def _FinaliseForTest():
85     """Remove the output directory (for use by tests)"""
86     global outdir
87
88     if outdir:
89         _RemoveOutputDir()
90
91 def SetInputDirs(dirname):
92     """Add a list of input directories, where input files are kept.
93
94     Args:
95         dirname: a list of paths to input directories to use for obtaining
96                 files needed by binman to place in the image.
97     """
98     global indir
99
100     indir = dirname
101     tout.Debug("Using input directories %s" % indir)
102
103 def GetInputFilename(fname):
104     """Return a filename for use as input.
105
106     Args:
107         fname: Filename to use for new file
108
109     Returns:
110         The full path of the filename, within the input directory
111     """
112     if not indir:
113         return fname
114     for dirname in indir:
115         pathname = os.path.join(dirname, fname)
116         if os.path.exists(pathname):
117             return pathname
118
119     raise ValueError("Filename '%s' not found in input path (%s) (cwd='%s')" %
120                      (fname, ','.join(indir), os.getcwd()))
121
122 def Align(pos, align):
123     if align:
124         mask = align - 1
125         pos = (pos + mask) & ~mask
126     return pos
127
128 def NotPowerOfTwo(num):
129     return num and (num & (num - 1))
130
131 def Run(name, *args):
132     command.Run(name, *args, cwd=outdir)
133
134 def Filename(fname):
135     """Resolve a file path to an absolute path.
136
137     If fname starts with ##/ and chroot is available, ##/ gets replaced with
138     the chroot path. If chroot is not available, this file name can not be
139     resolved, `None' is returned.
140
141     If fname is not prepended with the above prefix, and is not an existing
142     file, the actual file name is retrieved from the passed in string and the
143     search_paths directories (if any) are searched to for the file. If found -
144     the path to the found file is returned, `None' is returned otherwise.
145
146     Args:
147       fname: a string,  the path to resolve.
148
149     Returns:
150       Absolute path to the file or None if not found.
151     """
152     if fname.startswith('##/'):
153       if chroot_path:
154         fname = os.path.join(chroot_path, fname[3:])
155       else:
156         return None
157
158     # Search for a pathname that exists, and return it if found
159     if fname and not os.path.exists(fname):
160         for path in search_paths:
161             pathname = os.path.join(path, os.path.basename(fname))
162             if os.path.exists(pathname):
163                 return pathname
164
165     # If not found, just return the standard, unchanged path
166     return fname
167
168 def ReadFile(fname):
169     """Read and return the contents of a file.
170
171     Args:
172       fname: path to filename to read, where ## signifiies the chroot.
173
174     Returns:
175       data read from file, as a string.
176     """
177     with open(Filename(fname), 'rb') as fd:
178         data = fd.read()
179     #self._out.Info("Read file '%s' size %d (%#0x)" %
180                    #(fname, len(data), len(data)))
181     return data
182
183 def WriteFile(fname, data):
184     """Write data into a file.
185
186     Args:
187         fname: path to filename to write
188         data: data to write to file, as a string
189     """
190     #self._out.Info("Write file '%s' size %d (%#0x)" %
191                    #(fname, len(data), len(data)))
192     with open(Filename(fname), 'wb') as fd:
193         fd.write(data)