grim/convey
Clone
Summary
Browse
Changes
Graph
Merge the redux branch into default.
2021-12-20, Gary Kramlich
6b1dbda836d9
Merge the redux branch into default.
This officials abandons the 0.14.0 release and moves right on to 0.15.0 which
includes replacing docker with podman and simplifying many things.
// Convey
// Copyright 2016-2018 Gary Kramlich <grim@reaperworld.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package
environment
import
(
"fmt"
"os"
"strings"
)
type
envMapper
struct
{
env
[]
string
}
const
(
maxExpandWidth
=
100
)
// mapVariable replaces instances of the given name.
func
(
e
*
envMapper
)
mapVariable
(
name
string
)
string
{
// We might have something like $(pwd), in which case we don't want
// to wrap the name in `{}`, which would cause it to be ${}(pwd) and
// cannot be evaluated by a run task.
if
name
==
""
{
return
"$"
}
for
_
,
item
:=
range
e
.
env
{
if
parts
:=
strings
.
SplitN
(
item
,
"="
,
2
);
parts
[
0
]
==
name
{
if
len
(
parts
)
==
2
{
return
parts
[
1
]
}
return
os
.
Getenv
(
name
)
}
}
return
fmt
.
Sprintf
(
"${%s}"
,
name
)
}
// Map will return the value matching a KEY=VAL pair in the given environment.
func
Map
(
key
string
,
env
[]
string
)
string
{
val
,
_
:=
Mapper
(
key
,
env
)
return
val
}
// Mapper will replace ${TEMPLATE} patterns in the string with the KEY=VAL pairs
// in the given environment. This function will replace patterns recursively, so
// if VAL has the form ${TEMPLATE}, it will be replaced again.
func
Mapper
(
str
string
,
env
[]
string
)
(
string
,
error
)
{
mapper
:=
envMapper
{
env
}
orig
:=
str
last
:=
str
next
:=
os
.
Expand
(
last
,
mapper
.
mapVariable
)
prev
:=
map
[
string
]
struct
{}{}
for
i
:=
0
;
i
<
maxExpandWidth
;
i
++
{
if
last
==
next
{
return
next
,
nil
}
if
_
,
ok
:=
prev
[
next
];
ok
{
break
}
last
=
next
next
=
os
.
Expand
(
last
,
mapper
.
mapVariable
)
prev
[
last
]
=
struct
{}{}
}
return
""
,
fmt
.
Errorf
(
"infinite environment mapping loop while expanding '%s'"
,
orig
)
}
// SliceMapper calls Mapper for each item in a slice and returns a new slice.
func
SliceMapper
(
slice
,
env
[]
string
)
([]
string
,
error
)
{
mapped
:=
[]
string
{}
for
_
,
template
:=
range
slice
{
expanded
,
err
:=
Mapper
(
template
,
env
)
if
err
!=
nil
{
return
nil
,
err
}
mapped
=
append
(
mapped
,
expanded
)
}
return
mapped
,
nil
}