aboutsummaryrefslogtreecommitdiff
path: root/brep/submit/submit.bash.in
blob: babf081021b13ecb6afa51ef0cfe3736ec61e796 (plain)
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# file      : brep/submit/submit.bash.in
# copyright : Copyright (c) 2014-2018 Code Synthesis Ltd
# license   : MIT; see accompanying LICENSE file

# Utility functions useful for implementing submission handlers.

if [ "$brep_submit" ]; then
  return 0
else
  brep_submit=true
fi

@import libbutl/manifest-parser@
@import libbutl/manifest-serializer@

# Diagnostics.
#
# We expect the user to set the verbose variable either to true or empty
# (false).
#
if [ ! -v verbose ]; then
  echo "error: variable 'verbose' is not set" >&2
  exit 1
fi

# Normally the brep module's log record looks like this:
#
# [Mon Jul 23 17:48:46.945079 2018] [brep:error] [pid 123:tid 456] [brep::submit::init]: error description
#
# We will use the (almost) same format for our diagnostics (redirected to the
# Apache's error_log), so it can easily be attributed to the brep module.
#
info_self="$(basename $0)"

if [ "$#" -gt 0 ]; then
  info_ref="$(basename "${!#/}")" # Last argument is the submission directory.
fi

function info () # <severity> <text>
{
  local severity="$1"
  shift

  # Note: %N is Linux-specific.
  #
  local ts
  if ! ts="$(date +"%a %b %d %H:%M:%S.%6N %Y")"; then
    ts=
  fi

  echo "[$ts] [brep:$severity] [ref $info_ref] [$info_self]: $*" 1>&2;
}

function error () { info "error" "$*"; exit 1; }

function trace () { if [ "$verbose" ]; then info "info" "$*"; fi }

# Trace a command line, quoting empty arguments as well as those that contain
# spaces.
#
function trace_cmd () # <cmd> <arg>...
{
  if [ "$verbose" ]; then
    local s="+"
    while [ $# -gt 0 ]; do
      if [ -z "$1" -o -z "${1##* *}" ]; then
	s="$s '$1'"
      else
	s="$s $1"
      fi

      shift
    done

    info "info" "$s"
  fi
}

# Trace the current function name and arguments.
#
function trace_func () # <args>...
{
  trace_cmd "${FUNCNAME[1]}" "$@"
}

# Trace and run a command.
#
function run () # <cmd> <arg>...
{
  trace_cmd "$@"
  "$@"
}

# Same as above but also redirect the command stderr to /dev/null, unless
# running in the verbose mode.
#
# Note that we don't redirect stdout, so it can still be captured.
#
function run_silent () # <cmd> <arg>...
{
  trace_cmd "$@"

  if [ "$verbose" ]; then
    "$@"
  else
    "$@" 2>/dev/null
  fi
}

# Wrap libbutl manifest parsing/serializing functions to shorten names and to
# add tracing.
#
function manifest_parser_start () # [<file>]
{
  trace_func "$@"
  butl_manifest_parser_start "$@"

  manifest_parser_ofd="$butl_manifest_parser_ofd"
}

function manifest_parser_finish ()
{
  trace_func
  butl_manifest_parser_finish
}

function manifest_serializer_start () # [<file>]
{
  trace_func "$@"
  butl_manifest_serializer_start "$@"

  manifest_serializer_ifd="$butl_manifest_serializer_ifd"
}

function manifest_serializer_finish ()
{
  trace_func
  butl_manifest_serializer_finish
}

# Serialize one manifest name/value pair.
#
function manifest_serialize () # <name> <value>
{
#  trace "$1: $2"
  printf "%s:%s\0" "$1" "$2" >&"$manifest_serializer_ifd"
}

# Serialize the submission result manifest to stdout and exit the (sub-)shell
# with the zero status.
#
function exit_with_manifest () # <status> <message> [<reference>]
{
  trace_func "$@"

  local sts="$1"
  local msg="$2"
  local ref="$3"

  manifest_serializer_start

  manifest_serialize ""        "1"    # Start of manifest.
  manifest_serialize "status"  "$sts"
  manifest_serialize "message" "$msg"

  if [ -n "$ref" ]; then
    if [ "$sts" != "200" ]; then
      error "reference for code $sts"
    fi

    manifest_serialize "reference" "$ref"
  elif [ "$sts" == "200" ]; then
    error "no reference for code $sts"
  fi

  manifest_serializer_finish
  run exit 0
}

# Verify archive is a valid package and extract its manifest into
# <manifest> file.
#
function extract_package_manifest () # <archive> <manifest>
{
  local arc="$1"
  local man="$2"

  if ! run_silent bpkg pkg-verify --manifest "$arc" >"$man"; then
    # Perform the sanity check to make sure that bpkg is runnable.
    #
    if ! run bpkg --version >/dev/null; then
      error "unable to run bpkg"
    fi

    exit_with_manifest 400 "archive is not a valid package (run bpkg pkg-verify for details)"
  fi
}