<commit_before>package prelude

const jsmapping = `
var $jsObjectPtr, $jsErrorPtr;

var $needsExternalization = function(t) {
  switch (t.kind) {
    case $kindBool:
    case $kindInt:
    case $kindInt8:
    case $kindInt16:
    case $kindInt32:
    case $kindUint:
    case $kindUint8:
    case $kindUint16:
    case $kindUint32:
    case $kindUintptr:
    case $kindFloat32:
    case $kindFloat64:
      return false;
    default:
      return t !== $jsObjectPtr;
  }
};

var $externalize = function(v, t) {
  if (t === $jsObjectPtr) {
    return v;
  }
  switch (t.kind) {
  case $kindBool:
  case $kindInt:
  case $kindInt8:
  case $kindInt16:
  case $kindInt32:
  case $kindUint:
  case $kindUint8:
  case $kindUint16:
  case $kindUint32:
  case $kindUintptr:
  case $kindFloat32:
  case $kindFloat64:
    return v;
  case $kindInt64:
  case $kindUint64:
    return $flatten64(v);
  case $kindArray:
    if ($needsExternalization(t.elem)) {
      return $mapArray(v, function(e) { return $externalize(e, t.elem); });
    }
    return v;
  case $kindFunc:
    return $externalizeFunction(v, t, false);
  case $kindInterface:
    if (v === $ifaceNil) {
      return null;
    }
    if (v.constructor === $jsObjectPtr) {
      return v.$val.object;
    }
    return $externalize(v.$val, v.constructor);
  case $kindMap:
    var m = {};
    var keys = $keys(v);
    for (var i = 0; i < keys.length; i++) {
      var entry = v[keys[i]];
      m[$externalize(entry.k, t.key)] = $externalize(entry.v, t.elem);
    }
    return m;
  case $kindPtr:
    if (v === t.nil) {
      return null;
    }
    return $externalize(v.$get(), t.elem);
  case $kindSlice:
    if ($needsExternalization(t.elem)) {
      return $mapArray($sliceToArray(v), function(e) { return $externalize(e, t.elem); });
    }
    return $sliceToArray(v);
  case $kindString:
    if (v.search(/^[\x00-\x7F]*$/) !== -1) {
      return v;
    }
    var s = "", r;
    for (var i = 0; i < v.length; i += r[1]) {
      r = $decodeRune(v, i);
      var c = r[0];
      if (c > 0xFFFF) {
        var h = Math.floor((c - 0x10000) / 0x400) + 0xD800;
        var l = (c - 0x10000) % 0x400 + 0xDC00;
        s += String.fromCharCode(h, l);
        continue;
      }
      s += String.fromCharCode(c);
    }
    return s;
  case $kindStruct:
    var timePkg = $packages["time"];
    if (timePkg !== undefined && v.constructor === timePkg.Time.ptr) {
      var milli = $div64(v.UnixNano(), new $Int64(0, 1000000));
      return new Date($flatten64(milli));
    }

    var noJsObject = {};
    var searchJsObject = function(v, t) {
      if (t === $jsObjectPtr) {
        return v;
      }
      switch (t.kind) {
      case $kindPtr:
        if (v === t.nil) {
          return noJsObject;
        }
        return searchJsObject(v.$get(), t.elem);
      case $kindStruct:
        var f = t.fields[0];
        return searchJsObject(v[f.prop], f.typ);
      case $kindInterface:
        return searchJsObject(v.$val, v.constructor);
      default:
        return noJsObject;
      }
    };
    var o = searchJsObject(v, t);
    if (o !== noJsObject) {
      return o;
    }

    o = {};
    for (var i = 0; i < t.fields.length; i++) {
      var f = t.fields[i];
      if (f.pkg !== "") { /* not exported */
        continue;
      }
      o[f.name] = $externalize(v[f.prop], f.typ);
    }
    return o;
  }
  $panic(new $String("cannot externalize " + t.string));
};

var $externalizeFunction = function(v, t, passThis) {
  if (v === $throwNilPointerError) {
    return null;
  }
  if (v.$externalizeWrapper === undefined) {
    $checkForDeadlock = false;
    v.$externalizeWrapper = function() {
      var args = [];
      for (var i = 0; i < t.params.length; i++) {
        if (t.variadic && i === t.params.length - 1) {
          var vt = t.params[i].elem, varargs = [];
          for (var j = i; j < arguments.length; j++) {
            varargs.push($internalize(arguments[j], vt));
          }
          args.push(new (t.params[i])(varargs));
          break;
        }
        args.push($internalize(arguments[i], t.params[i]));
      }
      var canBlock = $curGoroutine.canBlock;
      $curGoroutine.canBlock = false;
      try {
        var result = v.apply(passThis ? this : undefined, args);
      } finally {
        $curGoroutine.canBlock = canBlock;
      }
      switch (t.results.length) {
      case 0:
        return;
      case 1:
        return $externalize(result, t.results[0]);
      default:
        for (var i = 0; i < t.results.length; i++) {
          result[i] = $externalize(result[i], t.results[i]);
        }
        return result;
      }
    };
  }
  return v.$externalizeWrapper;
};

var $internalize = function(v, t, recv) {
  if (t === $jsObjectPtr) {
    return v;
  }
  if (t === $jsObjectPtr.elem) {
    $panic(new $String("cannot internalize js.Object, use *js.Object instead"));
  }
  if (v && v.__internal_object__ !== undefined) {
    return $assertType(v.__internal_object__, t, false);
  }
  var timePkg = $packages["time"];
  if (timePkg !== undefined && t === timePkg.Time) {
    if (!(v !== null && v !== undefined && v.constructor === Date)) {
      $panic(new $String("cannot internalize time.Time from " + typeof v + ", must be Date"));
    }
    return timePkg.Unix(new $Int64(0, 0), new $Int64(0, v.getTime() * 1000000));
  }
  switch (t.kind) {
  case $kindBool:
    return !!v;
  case $kindInt:
    return parseInt(v);
  case $kindInt8:
    return parseInt(v) << 24 >> 24;
  case $kindInt16:
    return parseInt(v) << 16 >> 16;
  case $kindInt32:
    return parseInt(v) >> 0;
  case $kindUint:
    return parseInt(v);
  case $kindUint8:
    return parseInt(v) << 24 >>> 24;
  case $kindUint16:
    return parseInt(v) << 16 >>> 16;
  case $kindUint32:
  case $kindUintptr:
    return parseInt(v) >>> 0;
  case $kindInt64:
  case $kindUint64:
    return new t(0, v);
  case $kindFloat32:
  case $kindFloat64:
    return parseFloat(v);
  case $kindArray:
    if (v.length !== t.len) {
      $throwRuntimeError("got array with wrong size from JavaScript native");
    }
    return $mapArray(v, function(e) { return $internalize(e, t.elem); });
  case $kindFunc:
    return function() {
      var args = [];
      for (var i = 0; i < t.params.length; i++) {
        if (t.variadic && i === t.params.length - 1) {
          var vt = t.params[i].elem, varargs = arguments[i];
          for (var j = 0; j < varargs.$length; j++) {
            args.push($externalize(varargs.$array[varargs.$offset + j], vt));
          }
          break;
        }
        args.push($externalize(arguments[i], t.params[i]));
      }
      var result = v.apply(recv, args);
      switch (t.results.length) {
      case 0:
        return;
      case 1:
        return $internalize(result, t.results[0]);
      default:
        for (var i = 0; i < t.results.length; i++) {
          result[i] = $internalize(result[i], t.results[i]);
        }
        return result;
      }
    };
  case $kindInterface:
    if (t.methods.length !== 0) {
      $panic(new $String("cannot internalize " + t.string));
    }
    if (v === null) {
      return $ifaceNil;
    }
    if (v === undefined) {
      return new $jsObjectPtr(undefined);
    }
    switch (v.constructor) {
    case Int8Array:
      return new ($sliceType($Int8))(v);
    case Int16Array:
      return new ($sliceType($Int16))(v);
    case Int32Array:
      return new ($sliceType($Int))(v);
    case Uint8Array:
      return new ($sliceType($Uint8))(v);
    case Uint16Array:
      return new ($sliceType($Uint16))(v);
    case Uint32Array:
      return new ($sliceType($Uint))(v);
    case Float32Array:
      return new ($sliceType($Float32))(v);
    case Float64Array:
      return new ($sliceType($Float64))(v);
    case Array:
      return $internalize(v, $sliceType($emptyInterface));
    case Boolean:
      return new $Bool(!!v);
    case Date:
      if (timePkg === undefined) {
        /* time package is not present, internalize as &js.Object{Date} so it can be externalized into original Date. */
        return new $jsObjectPtr(v);
      }
      return new timePkg.Time($internalize(v, timePkg.Time));
    case Function:
      var funcType = $funcType([$sliceType($emptyInterface)], [$jsObjectPtr], true);
      return new funcType($internalize(v, funcType));
    case Number:
      return new $Float64(parseFloat(v));
    case String:
      return new $String($internalize(v, $String));
    default:
      if ($global.Node && v instanceof $global.Node) {
        return new $jsObjectPtr(v);
      }
      var mapType = $mapType($String, $emptyInterface);
      return new mapType($internalize(v, mapType));
    }
  case $kindMap:
    var m = {};
    var keys = $keys(v);
    for (var i = 0; i < keys.length; i++) {
      var k = $internalize(keys[i], t.key);
      m[t.key.keyFor(k)] = { k: k, v: $internalize(v[keys[i]], t.elem) };
    }
    return m;
  case $kindPtr:
    if (t.elem.kind === $kindStruct) {
      return $internalize(v, t.elem);
    }
  case $kindSlice:
    return new t($mapArray(v, function(e) { return $internalize(e, t.elem); }));
  case $kindString:
    v = String(v);
    if (v.search(/^[\x00-\x7F]*$/) !== -1) {
      return v;
    }
    var s = "";
    var i = 0;
    while (i < v.length) {
      var h = v.charCodeAt(i);
      if (0xD800 <= h && h <= 0xDBFF) {
        var l = v.charCodeAt(i + 1);
        var c = (h - 0xD800) * 0x400 + l - 0xDC00 + 0x10000;
        s += $encodeRune(c);
        i += 2;
        continue;
      }
      s += $encodeRune(h);
      i++;
    }
    return s;
  case $kindStruct:
    var noJsObject = {};
    var searchJsObject = function(t) {
      if (t === $jsObjectPtr) {
        return v;
      }
      if (t === $jsObjectPtr.elem) {
        $panic(new $String("cannot internalize js.Object, use *js.Object instead"));
      }
      switch (t.kind) {
      case $kindPtr:
        return searchJsObject(t.elem);
      case $kindStruct:
        var f = t.fields[0];
        var o = searchJsObject(f.typ);
        if (o !== noJsObject) {
          var n = new t.ptr();
          n[f.prop] = o;
          return n;
        }
        return noJsObject;
      default:
        return noJsObject;
      }
    };
    var o = searchJsObject(t);
    if (o !== noJsObject) {
      return o;
    }
  }
  $panic(new $String("cannot internalize " + t.string));
};
`
<commit_msg>jsmapping: panic with proper runtime errors<commit_after>package prelude

const jsmapping = `
var $jsObjectPtr, $jsErrorPtr;

var $needsExternalization = function(t) {
  switch (t.kind) {
    case $kindBool:
    case $kindInt:
    case $kindInt8:
    case $kindInt16:
    case $kindInt32:
    case $kindUint:
    case $kindUint8:
    case $kindUint16:
    case $kindUint32:
    case $kindUintptr:
    case $kindFloat32:
    case $kindFloat64:
      return false;
    default:
      return t !== $jsObjectPtr;
  }
};

var $externalize = function(v, t) {
  if (t === $jsObjectPtr) {
    return v;
  }
  switch (t.kind) {
  case $kindBool:
  case $kindInt:
  case $kindInt8:
  case $kindInt16:
  case $kindInt32:
  case $kindUint:
  case $kindUint8:
  case $kindUint16:
  case $kindUint32:
  case $kindUintptr:
  case $kindFloat32:
  case $kindFloat64:
    return v;
  case $kindInt64:
  case $kindUint64:
    return $flatten64(v);
  case $kindArray:
    if ($needsExternalization(t.elem)) {
      return $mapArray(v, function(e) { return $externalize(e, t.elem); });
    }
    return v;
  case $kindFunc:
    return $externalizeFunction(v, t, false);
  case $kindInterface:
    if (v === $ifaceNil) {
      return null;
    }
    if (v.constructor === $jsObjectPtr) {
      return v.$val.object;
    }
    return $externalize(v.$val, v.constructor);
  case $kindMap:
    var m = {};
    var keys = $keys(v);
    for (var i = 0; i < keys.length; i++) {
      var entry = v[keys[i]];
      m[$externalize(entry.k, t.key)] = $externalize(entry.v, t.elem);
    }
    return m;
  case $kindPtr:
    if (v === t.nil) {
      return null;
    }
    return $externalize(v.$get(), t.elem);
  case $kindSlice:
    if ($needsExternalization(t.elem)) {
      return $mapArray($sliceToArray(v), function(e) { return $externalize(e, t.elem); });
    }
    return $sliceToArray(v);
  case $kindString:
    if (v.search(/^[\x00-\x7F]*$/) !== -1) {
      return v;
    }
    var s = "", r;
    for (var i = 0; i < v.length; i += r[1]) {
      r = $decodeRune(v, i);
      var c = r[0];
      if (c > 0xFFFF) {
        var h = Math.floor((c - 0x10000) / 0x400) + 0xD800;
        var l = (c - 0x10000) % 0x400 + 0xDC00;
        s += String.fromCharCode(h, l);
        continue;
      }
      s += String.fromCharCode(c);
    }
    return s;
  case $kindStruct:
    var timePkg = $packages["time"];
    if (timePkg !== undefined && v.constructor === timePkg.Time.ptr) {
      var milli = $div64(v.UnixNano(), new $Int64(0, 1000000));
      return new Date($flatten64(milli));
    }

    var noJsObject = {};
    var searchJsObject = function(v, t) {
      if (t === $jsObjectPtr) {
        return v;
      }
      switch (t.kind) {
      case $kindPtr:
        if (v === t.nil) {
          return noJsObject;
        }
        return searchJsObject(v.$get(), t.elem);
      case $kindStruct:
        var f = t.fields[0];
        return searchJsObject(v[f.prop], f.typ);
      case $kindInterface:
        return searchJsObject(v.$val, v.constructor);
      default:
        return noJsObject;
      }
    };
    var o = searchJsObject(v, t);
    if (o !== noJsObject) {
      return o;
    }

    o = {};
    for (var i = 0; i < t.fields.length; i++) {
      var f = t.fields[i];
      if (f.pkg !== "") { /* not exported */
        continue;
      }
      o[f.name] = $externalize(v[f.prop], f.typ);
    }
    return o;
  }
  $throwRuntimeError("cannot externalize " + t.string);
};

var $externalizeFunction = function(v, t, passThis) {
  if (v === $throwNilPointerError) {
    return null;
  }
  if (v.$externalizeWrapper === undefined) {
    $checkForDeadlock = false;
    v.$externalizeWrapper = function() {
      var args = [];
      for (var i = 0; i < t.params.length; i++) {
        if (t.variadic && i === t.params.length - 1) {
          var vt = t.params[i].elem, varargs = [];
          for (var j = i; j < arguments.length; j++) {
            varargs.push($internalize(arguments[j], vt));
          }
          args.push(new (t.params[i])(varargs));
          break;
        }
        args.push($internalize(arguments[i], t.params[i]));
      }
      var canBlock = $curGoroutine.canBlock;
      $curGoroutine.canBlock = false;
      try {
        var result = v.apply(passThis ? this : undefined, args);
      } finally {
        $curGoroutine.canBlock = canBlock;
      }
      switch (t.results.length) {
      case 0:
        return;
      case 1:
        return $externalize(result, t.results[0]);
      default:
        for (var i = 0; i < t.results.length; i++) {
          result[i] = $externalize(result[i], t.results[i]);
        }
        return result;
      }
    };
  }
  return v.$externalizeWrapper;
};

var $internalize = function(v, t, recv) {
  if (t === $jsObjectPtr) {
    return v;
  }
  if (t === $jsObjectPtr.elem) {
    $throwRuntimeError("cannot internalize js.Object, use *js.Object instead");
  }
  if (v && v.__internal_object__ !== undefined) {
    return $assertType(v.__internal_object__, t, false);
  }
  var timePkg = $packages["time"];
  if (timePkg !== undefined && t === timePkg.Time) {
    if (!(v !== null && v !== undefined && v.constructor === Date)) {
      $throwRuntimeError("cannot internalize time.Time from " + typeof v + ", must be Date");
    }
    return timePkg.Unix(new $Int64(0, 0), new $Int64(0, v.getTime() * 1000000));
  }
  switch (t.kind) {
  case $kindBool:
    return !!v;
  case $kindInt:
    return parseInt(v);
  case $kindInt8:
    return parseInt(v) << 24 >> 24;
  case $kindInt16:
    return parseInt(v) << 16 >> 16;
  case $kindInt32:
    return parseInt(v) >> 0;
  case $kindUint:
    return parseInt(v);
  case $kindUint8:
    return parseInt(v) << 24 >>> 24;
  case $kindUint16:
    return parseInt(v) << 16 >>> 16;
  case $kindUint32:
  case $kindUintptr:
    return parseInt(v) >>> 0;
  case $kindInt64:
  case $kindUint64:
    return new t(0, v);
  case $kindFloat32:
  case $kindFloat64:
    return parseFloat(v);
  case $kindArray:
    if (v.length !== t.len) {
      $throwRuntimeError("got array with wrong size from JavaScript native");
    }
    return $mapArray(v, function(e) { return $internalize(e, t.elem); });
  case $kindFunc:
    return function() {
      var args = [];
      for (var i = 0; i < t.params.length; i++) {
        if (t.variadic && i === t.params.length - 1) {
          var vt = t.params[i].elem, varargs = arguments[i];
          for (var j = 0; j < varargs.$length; j++) {
            args.push($externalize(varargs.$array[varargs.$offset + j], vt));
          }
          break;
        }
        args.push($externalize(arguments[i], t.params[i]));
      }
      var result = v.apply(recv, args);
      switch (t.results.length) {
      case 0:
        return;
      case 1:
        return $internalize(result, t.results[0]);
      default:
        for (var i = 0; i < t.results.length; i++) {
          result[i] = $internalize(result[i], t.results[i]);
        }
        return result;
      }
    };
  case $kindInterface:
    if (t.methods.length !== 0) {
      $throwRuntimeError("cannot internalize " + t.string);
    }
    if (v === null) {
      return $ifaceNil;
    }
    if (v === undefined) {
      return new $jsObjectPtr(undefined);
    }
    switch (v.constructor) {
    case Int8Array:
      return new ($sliceType($Int8))(v);
    case Int16Array:
      return new ($sliceType($Int16))(v);
    case Int32Array:
      return new ($sliceType($Int))(v);
    case Uint8Array:
      return new ($sliceType($Uint8))(v);
    case Uint16Array:
      return new ($sliceType($Uint16))(v);
    case Uint32Array:
      return new ($sliceType($Uint))(v);
    case Float32Array:
      return new ($sliceType($Float32))(v);
    case Float64Array:
      return new ($sliceType($Float64))(v);
    case Array:
      return $internalize(v, $sliceType($emptyInterface));
    case Boolean:
      return new $Bool(!!v);
    case Date:
      if (timePkg === undefined) {
        /* time package is not present, internalize as &js.Object{Date} so it can be externalized into original Date. */
        return new $jsObjectPtr(v);
      }
      return new timePkg.Time($internalize(v, timePkg.Time));
    case Function:
      var funcType = $funcType([$sliceType($emptyInterface)], [$jsObjectPtr], true);
      return new funcType($internalize(v, funcType));
    case Number:
      return new $Float64(parseFloat(v));
    case String:
      return new $String($internalize(v, $String));
    default:
      if ($global.Node && v instanceof $global.Node) {
        return new $jsObjectPtr(v);
      }
      var mapType = $mapType($String, $emptyInterface);
      return new mapType($internalize(v, mapType));
    }
  case $kindMap:
    var m = {};
    var keys = $keys(v);
    for (var i = 0; i < keys.length; i++) {
      var k = $internalize(keys[i], t.key);
      m[t.key.keyFor(k)] = { k: k, v: $internalize(v[keys[i]], t.elem) };
    }
    return m;
  case $kindPtr:
    if (t.elem.kind === $kindStruct) {
      return $internalize(v, t.elem);
    }
  case $kindSlice:
    return new t($mapArray(v, function(e) { return $internalize(e, t.elem); }));
  case $kindString:
    v = String(v);
    if (v.search(/^[\x00-\x7F]*$/) !== -1) {
      return v;
    }
    var s = "";
    var i = 0;
    while (i < v.length) {
      var h = v.charCodeAt(i);
      if (0xD800 <= h && h <= 0xDBFF) {
        var l = v.charCodeAt(i + 1);
        var c = (h - 0xD800) * 0x400 + l - 0xDC00 + 0x10000;
        s += $encodeRune(c);
        i += 2;
        continue;
      }
      s += $encodeRune(h);
      i++;
    }
    return s;
  case $kindStruct:
    var noJsObject = {};
    var searchJsObject = function(t) {
      if (t === $jsObjectPtr) {
        return v;
      }
      if (t === $jsObjectPtr.elem) {
        $throwRuntimeError("cannot internalize js.Object, use *js.Object instead");
      }
      switch (t.kind) {
      case $kindPtr:
        return searchJsObject(t.elem);
      case $kindStruct:
        var f = t.fields[0];
        var o = searchJsObject(f.typ);
        if (o !== noJsObject) {
          var n = new t.ptr();
          n[f.prop] = o;
          return n;
        }
        return noJsObject;
      default:
        return noJsObject;
      }
    };
    var o = searchJsObject(t);
    if (o !== noJsObject) {
      return o;
    }
  }
  $throwRuntimeError("cannot internalize " + t.string);
};
`
<|endoftext|>


<commit_before>/*
Copyright 2019 The Knative Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

	http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package certificate

import (
	"context"
	"fmt"
	"reflect"

	cmv1alpha1 "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
	"go.uber.org/zap"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/equality"
	apierrs "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/tools/cache"
	"knative.dev/pkg/controller"
	"knative.dev/pkg/logging"
	"knative.dev/serving/pkg/apis/networking/v1alpha1"
	certmanagerclientset "knative.dev/serving/pkg/client/certmanager/clientset/versioned"
	certmanagerlisters "knative.dev/serving/pkg/client/certmanager/listers/certmanager/v1alpha1"
	listers "knative.dev/serving/pkg/client/listers/networking/v1alpha1"
	"knative.dev/serving/pkg/reconciler"
	"knative.dev/serving/pkg/reconciler/certificate/config"
	"knative.dev/serving/pkg/reconciler/certificate/resources"
)

const (
	noCMConditionReason  = "NoCertManagerCertCondition"
	noCMConditionMessage = "The ready condition of Cert Manager Certifiate does not exist."
)

// Reconciler implements controller.Reconciler for Certificate resources.
type Reconciler struct {
	*reconciler.Base

	// listers index properties about resources
	knCertificateLister listers.CertificateLister
	cmCertificateLister certmanagerlisters.CertificateLister
	certManagerClient   certmanagerclientset.Interface

	configStore reconciler.ConfigStore
}

// Check that our Reconciler implements controller.Reconciler
var _ controller.Reconciler = (*Reconciler)(nil)

// Reconcile compares the actual state with the desired, and attempts to
// converge the two. It then updates the Status block of the Certificate resource
// with the current status of the resource.
func (c *Reconciler) Reconcile(ctx context.Context, key string) error {
	// Convert the namespace/name string into a distinct namespace and name
	namespace, name, err := cache.SplitMetaNamespaceKey(key)
	if err != nil {
		c.Logger.Errorf("invalid resource key: %s", key)
		return nil
	}
	logger := logging.FromContext(ctx)
	ctx = c.configStore.ToContext(ctx)

	original, err := c.knCertificateLister.Certificates(namespace).Get(name)
	if apierrs.IsNotFound(err) {
		logger.Errorf("Knative Certificate %s in work queue no longer exists", key)
		return nil
	} else if err != nil {
		return err
	}

	// Don't modify the informers copy
	knCert := original.DeepCopy()

	// Reconcile this copy of the Certificate and then write back any status
	// updates regardless of whether the reconciliation errored out.
	err = c.reconcile(ctx, knCert)
	if equality.Semantic.DeepEqual(original.Status, knCert.Status) {
		// If we didn't change anything then don't call updateStatus.
		// This is important because the copy we loaded from the informer's
		// cache may be stale and we don't want to overwrite a prior update
		// to status with this stale state.
	} else if _, err := c.updateStatus(knCert); err != nil {
		logger.Warnw("Failed to update certificate status", zap.Error(err))
		c.Recorder.Eventf(knCert, corev1.EventTypeWarning, "UpdateFailed",
			"Failed to update status for Certificate %s: %v", key, err)
		return err
	}
	if err != nil {
		c.Recorder.Event(knCert, corev1.EventTypeWarning, "InternalError", err.Error())
	}
	return err
}

func (c *Reconciler) reconcile(ctx context.Context, knCert *v1alpha1.Certificate) error {
	logger := logging.FromContext(ctx)

	knCert.SetDefaults(ctx)
	knCert.Status.InitializeConditions()

	logger.Info("Reconciling Cert-Manager certificate for Knative cert %s/%s.", knCert.Namespace, knCert.Name)
	cmConfig := config.FromContext(ctx).CertManager
	cmCert := resources.MakeCertManagerCertificate(cmConfig, knCert)
	cmCert, err := c.reconcileCMCertificate(ctx, knCert, cmCert)
	if err != nil {
		return err
	}

	knCert.Status.NotAfter = cmCert.Status.NotAfter
	knCert.Status.ObservedGeneration = knCert.Generation
	// Propagate cert-manager Certificate status to Knative Certificate.
	cmCertReadyCondition := resources.GetReadyCondition(cmCert)
	switch {
	case cmCertReadyCondition == nil:
		knCert.Status.MarkUnknown(noCMConditionReason, noCMConditionMessage)
	case cmCertReadyCondition.Status == cmv1alpha1.ConditionUnknown:
		knCert.Status.MarkUnknown(cmCertReadyCondition.Reason, cmCertReadyCondition.Message)
	case cmCertReadyCondition.Status == cmv1alpha1.ConditionTrue:
		knCert.Status.MarkReady()
	case cmCertReadyCondition.Status == cmv1alpha1.ConditionFalse:
		knCert.Status.MarkNotReady(cmCertReadyCondition.Reason, cmCertReadyCondition.Message)
	}
	return nil
}

func (c *Reconciler) reconcileCMCertificate(ctx context.Context, knCert *v1alpha1.Certificate, desired *cmv1alpha1.Certificate) (*cmv1alpha1.Certificate, error) {
	logger := logging.FromContext(ctx)
	cmCert, err := c.cmCertificateLister.Certificates(desired.Namespace).Get(desired.Name)
	if apierrs.IsNotFound(err) {
		cmCert, err = c.certManagerClient.CertmanagerV1alpha1().Certificates(desired.Namespace).Create(desired)
		if err != nil {
			logger.Errorw("Failed to create Cert-Manager certificate", zap.Error(err))
			c.Recorder.Eventf(knCert, corev1.EventTypeWarning, "CreationFailed",
				"Failed to create Cert-Manager Certificate %s/%s: %v", desired.Name, desired.Namespace, err)
			return nil, err
		}
		c.Recorder.Eventf(knCert, corev1.EventTypeNormal, "Created",
			"Created Cert-Manager Certificate %s/%s", desired.Namespace, desired.Name)
	} else if err != nil {
		return nil, err
	} else if !metav1.IsControlledBy(desired, knCert) {
		knCert.Status.MarkResourceNotOwned("CertManagerCertificate", desired.Name)
		return nil, fmt.Errorf("knative Certificate %s in namespace %s does not own CertManager Certificate: %s", knCert.Name, knCert.Namespace, desired.Name)
	} else if !equality.Semantic.DeepEqual(cmCert.Spec, desired.Spec) {
		copy := cmCert.DeepCopy()
		copy.Spec = desired.Spec
		updated, err := c.certManagerClient.CertmanagerV1alpha1().Certificates(copy.Namespace).Update(copy)
		if err != nil {
			logger.Errorw("Failed to update Cert-Manager Certificate", zap.Error(err))
			c.Recorder.Eventf(knCert, corev1.EventTypeWarning, "UpdateFailed",
				"Failed to create Cert-Manager Certificate %s/%s: %v", desired.Namespace, desired.Name, err)
			return nil, err
		}
		c.Recorder.Eventf(knCert, corev1.EventTypeNormal, "Updated",
			"Updated Spec for Cert-Manager Certificate %s/%s", desired.Namespace, desired.Name)
		return updated, nil
	}
	return cmCert, nil
}

func (c *Reconciler) updateStatus(desired *v1alpha1.Certificate) (*v1alpha1.Certificate, error) {
	cert, err := c.knCertificateLister.Certificates(desired.Namespace).Get(desired.Name)
	if err != nil {
		return nil, err
	}
	// If there's nothing to update, just return.
	if reflect.DeepEqual(cert.Status, desired.Status) {
		return cert, nil
	}
	// Don't modify the informers copy
	existing := cert.DeepCopy()
	existing.Status = desired.Status

	return c.ServingClientSet.NetworkingV1alpha1().Certificates(existing.Namespace).UpdateStatus(existing)
}
<commit_msg>Fix wrong log format in certificate (#5131)<commit_after>/*
Copyright 2019 The Knative Authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

	http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package certificate

import (
	"context"
	"fmt"
	"reflect"

	cmv1alpha1 "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1alpha1"
	"go.uber.org/zap"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/equality"
	apierrs "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/tools/cache"
	"knative.dev/pkg/controller"
	"knative.dev/pkg/logging"
	"knative.dev/serving/pkg/apis/networking/v1alpha1"
	certmanagerclientset "knative.dev/serving/pkg/client/certmanager/clientset/versioned"
	certmanagerlisters "knative.dev/serving/pkg/client/certmanager/listers/certmanager/v1alpha1"
	listers "knative.dev/serving/pkg/client/listers/networking/v1alpha1"
	"knative.dev/serving/pkg/reconciler"
	"knative.dev/serving/pkg/reconciler/certificate/config"
	"knative.dev/serving/pkg/reconciler/certificate/resources"
)

const (
	noCMConditionReason  = "NoCertManagerCertCondition"
	noCMConditionMessage = "The ready condition of Cert Manager Certifiate does not exist."
)

// Reconciler implements controller.Reconciler for Certificate resources.
type Reconciler struct {
	*reconciler.Base

	// listers index properties about resources
	knCertificateLister listers.CertificateLister
	cmCertificateLister certmanagerlisters.CertificateLister
	certManagerClient   certmanagerclientset.Interface

	configStore reconciler.ConfigStore
}

// Check that our Reconciler implements controller.Reconciler
var _ controller.Reconciler = (*Reconciler)(nil)

// Reconcile compares the actual state with the desired, and attempts to
// converge the two. It then updates the Status block of the Certificate resource
// with the current status of the resource.
func (c *Reconciler) Reconcile(ctx context.Context, key string) error {
	// Convert the namespace/name string into a distinct namespace and name
	namespace, name, err := cache.SplitMetaNamespaceKey(key)
	if err != nil {
		c.Logger.Errorf("invalid resource key: %s", key)
		return nil
	}
	logger := logging.FromContext(ctx)
	ctx = c.configStore.ToContext(ctx)

	original, err := c.knCertificateLister.Certificates(namespace).Get(name)
	if apierrs.IsNotFound(err) {
		logger.Errorf("Knative Certificate %s in work queue no longer exists", key)
		return nil
	} else if err != nil {
		return err
	}

	// Don't modify the informers copy
	knCert := original.DeepCopy()

	// Reconcile this copy of the Certificate and then write back any status
	// updates regardless of whether the reconciliation errored out.
	err = c.reconcile(ctx, knCert)
	if equality.Semantic.DeepEqual(original.Status, knCert.Status) {
		// If we didn't change anything then don't call updateStatus.
		// This is important because the copy we loaded from the informer's
		// cache may be stale and we don't want to overwrite a prior update
		// to status with this stale state.
	} else if _, err := c.updateStatus(knCert); err != nil {
		logger.Warnw("Failed to update certificate status", zap.Error(err))
		c.Recorder.Eventf(knCert, corev1.EventTypeWarning, "UpdateFailed",
			"Failed to update status for Certificate %s: %v", key, err)
		return err
	}
	if err != nil {
		c.Recorder.Event(knCert, corev1.EventTypeWarning, "InternalError", err.Error())
	}
	return err
}

func (c *Reconciler) reconcile(ctx context.Context, knCert *v1alpha1.Certificate) error {
	logger := logging.FromContext(ctx)

	knCert.SetDefaults(ctx)
	knCert.Status.InitializeConditions()

	logger.Infof("Reconciling Cert-Manager certificate for Knative cert %s/%s.", knCert.Namespace, knCert.Name)
	cmConfig := config.FromContext(ctx).CertManager
	cmCert := resources.MakeCertManagerCertificate(cmConfig, knCert)
	cmCert, err := c.reconcileCMCertificate(ctx, knCert, cmCert)
	if err != nil {
		return err
	}

	knCert.Status.NotAfter = cmCert.Status.NotAfter
	knCert.Status.ObservedGeneration = knCert.Generation
	// Propagate cert-manager Certificate status to Knative Certificate.
	cmCertReadyCondition := resources.GetReadyCondition(cmCert)
	switch {
	case cmCertReadyCondition == nil:
		knCert.Status.MarkUnknown(noCMConditionReason, noCMConditionMessage)
	case cmCertReadyCondition.Status == cmv1alpha1.ConditionUnknown:
		knCert.Status.MarkUnknown(cmCertReadyCondition.Reason, cmCertReadyCondition.Message)
	case cmCertReadyCondition.Status == cmv1alpha1.ConditionTrue:
		knCert.Status.MarkReady()
	case cmCertReadyCondition.Status == cmv1alpha1.ConditionFalse:
		knCert.Status.MarkNotReady(cmCertReadyCondition.Reason, cmCertReadyCondition.Message)
	}
	return nil
}

func (c *Reconciler) reconcileCMCertificate(ctx context.Context, knCert *v1alpha1.Certificate, desired *cmv1alpha1.Certificate) (*cmv1alpha1.Certificate, error) {
	logger := logging.FromContext(ctx)
	cmCert, err := c.cmCertificateLister.Certificates(desired.Namespace).Get(desired.Name)
	if apierrs.IsNotFound(err) {
		cmCert, err = c.certManagerClient.CertmanagerV1alpha1().Certificates(desired.Namespace).Create(desired)
		if err != nil {
			logger.Errorw("Failed to create Cert-Manager certificate", zap.Error(err))
			c.Recorder.Eventf(knCert, corev1.EventTypeWarning, "CreationFailed",
				"Failed to create Cert-Manager Certificate %s/%s: %v", desired.Name, desired.Namespace, err)
			return nil, err
		}
		c.Recorder.Eventf(knCert, corev1.EventTypeNormal, "Created",
			"Created Cert-Manager Certificate %s/%s", desired.Namespace, desired.Name)
	} else if err != nil {
		return nil, err
	} else if !metav1.IsControlledBy(desired, knCert) {
		knCert.Status.MarkResourceNotOwned("CertManagerCertificate", desired.Name)
		return nil, fmt.Errorf("knative Certificate %s in namespace %s does not own CertManager Certificate: %s", knCert.Name, knCert.Namespace, desired.Name)
	} else if !equality.Semantic.DeepEqual(cmCert.Spec, desired.Spec) {
		copy := cmCert.DeepCopy()
		copy.Spec = desired.Spec
		updated, err := c.certManagerClient.CertmanagerV1alpha1().Certificates(copy.Namespace).Update(copy)
		if err != nil {
			logger.Errorw("Failed to update Cert-Manager Certificate", zap.Error(err))
			c.Recorder.Eventf(knCert, corev1.EventTypeWarning, "UpdateFailed",
				"Failed to create Cert-Manager Certificate %s/%s: %v", desired.Namespace, desired.Name, err)
			return nil, err
		}
		c.Recorder.Eventf(knCert, corev1.EventTypeNormal, "Updated",
			"Updated Spec for Cert-Manager Certificate %s/%s", desired.Namespace, desired.Name)
		return updated, nil
	}
	return cmCert, nil
}

func (c *Reconciler) updateStatus(desired *v1alpha1.Certificate) (*v1alpha1.Certificate, error) {
	cert, err := c.knCertificateLister.Certificates(desired.Namespace).Get(desired.Name)
	if err != nil {
		return nil, err
	}
	// If there's nothing to update, just return.
	if reflect.DeepEqual(cert.Status, desired.Status) {
		return cert, nil
	}
	// Don't modify the informers copy
	existing := cert.DeepCopy()
	existing.Status = desired.Status

	return c.ServingClientSet.NetworkingV1alpha1().Certificates(existing.Namespace).UpdateStatus(existing)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/minchao/go-mitake"
)

func usage() {
	fmt.Println(`Usage: send [options]
Options are:
    -u  Mitake Username
    -p  Mitake Password
    -t  Destination phone number, for example: 0987654321
    -m  Message content`)
	os.Exit(0)
}

func main() {
	var (
		username string
		password string
		to       string
		message  string
	)

	flag.StringVar(&username, "u", os.Getenv("MITAKE_USERNAME"), "Username")
	flag.StringVar(&password, "p", os.Getenv("MITAKE_PASSWORD"), "Password")
	flag.StringVar(&to, "t", "", "Destination phone number")
	flag.StringVar(&message, "m", "", "Message content")

	flag.Usage = usage
	flag.Parse()

	if len(os.Args) < 2 {
		usage()
	}

	client := mitake.NewClient(username, password, nil)

	resp, err := client.Send(mitake.Message{
		Dstaddr: to,
		Smbody:  message,
	})
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	fmt.Fprintf(os.Stdout, "result: %+v\n", resp.INI)
}
<commit_msg>Improve example<commit_after>package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/minchao/go-mitake"
)

func usage() {
	fmt.Fprintln(os.Stderr, `Usage: send [options]`)
	flag.PrintDefaults()
}

func main() {
	var (
		username string
		password string
		to       string
		message  string
	)

	flag.StringVar(&username, "u", os.Getenv("MITAKE_USERNAME"), "Username")
	flag.StringVar(&password, "p", os.Getenv("MITAKE_PASSWORD"), "Password")
	flag.StringVar(&to, "t", "", "Destination phone number, for example: 0987654321")
	flag.StringVar(&message, "m", "", "Message content")

	flag.Usage = usage
	flag.Parse()

	if len(os.Args) < 3 {
		flag.Usage()
		os.Exit(1)
	}

	client := mitake.NewClient(username, password, nil)

	resp, err := client.Send(mitake.Message{
		Dstaddr: to,
		Smbody:  message,
	})
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}

	fmt.Fprintf(os.Stdout, "result: %+v\n", resp.INI)
}
<|endoftext|>


<commit_before>/*
 Copyright 2020 The GoPlus Authors (goplus.org)

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/

package exec

import (
	"reflect"
)

// -----------------------------------------------------------------------------

// Operator type.
type Operator uint

const (
	// OpInvalid - invalid operator
	OpInvalid Operator = iota
	// OpAdd '+' String/Int/Uint/Float/Complex
	OpAdd
	// OpSub '-' Int/Uint/Float/Complex
	OpSub
	// OpMul '*' Int/Uint/Float/Complex
	OpMul
	// OpQuo '/' Int/Uint/Float/Complex
	OpQuo
	// OpMod '%' Int/Uint
	OpMod
	// OpAnd '&' Int/Uint
	OpAnd
	// OpOr '|' Int/Uint
	OpOr
	// OpXor '^' Int/Uint
	OpXor
	// OpAndNot '&^' Int/Uint
	OpAndNot
	// OpLsh '<<' Int/Uint, Uint
	OpLsh
	// OpRsh '>>' Int/Uint, Uint
	OpRsh
	// OpLT '<' String/Int/Uint/Float
	OpLT
	// OpLE '<=' String/Int/Uint/Float
	OpLE
	// OpGT '>' String/Int/Uint/Float
	OpGT
	// OpGE '>=' String/Int/Uint/Float
	OpGE
	// OpEQ '==' ComparableType
	// Slice, map, and function values are not comparable. However, as a special case, a slice, map,
	// or function value may be compared to the predeclared identifier nil.
	OpEQ
	// OpEQNil '==' nil
	OpEQNil
	// OpNE '!=' ComparableType
	OpNE
	// OpNENil '!=' nil
	OpNENil
	// OpLAnd '&&' Bool
	OpLAnd
	// OpLOr '||' Bool
	OpLOr
	// OpLNot '!'
	OpLNot
	// OpNeg '-'
	OpNeg
	// OpBitNot '^'
	OpBitNot
)

const (
	// SameAsFirst means the second argument is same as first argument type.
	SameAsFirst = reflect.Invalid
)

const (
	bitNone          = 0
	bitSameAsFirst   = 1 << SameAsFirst
	bitBool          = 1 << Bool
	bitInt           = 1 << Int
	bitInt8          = 1 << Int8
	bitInt16         = 1 << Int16
	bitInt32         = 1 << Int32
	bitInt64         = 1 << Int64
	bitUint          = 1 << Uint
	bitUint8         = 1 << Uint8
	bitUint16        = 1 << Uint16
	bitUint32        = 1 << Uint32
	bitUint64        = 1 << Uint64
	bitUintptr       = 1 << Uintptr
	bitFloat32       = 1 << Float32
	bitFloat64       = 1 << Float64
	bitComplex64     = 1 << Complex64
	bitComplex128    = 1 << Complex128
	bitString        = 1 << String
	bitUnsafePointer = 1 << UnsafePointer
	bitPtr           = 1 << reflect.Ptr
	bitBigInt        = 1 << BigInt
	bitBigRat        = 1 << BigRat
	bitBigFloat      = 1 << BigFloat

	bitsAllInt     = bitInt | bitInt8 | bitInt16 | bitInt32 | bitInt64
	bitsAllUint    = bitUint | bitUint8 | bitUint16 | bitUint32 | bitUint64 | bitUintptr
	bitsAllIntUint = bitsAllInt | bitsAllUint
	bitsAllFloat   = bitFloat32 | bitFloat64
	bitsAllReal    = bitsAllIntUint | bitsAllFloat | bitBigRat | bitBigFloat
	bitsAllComplex = bitComplex64 | bitComplex128
	bitsAllNumber  = bitsAllReal | bitsAllComplex
	bitsAllPtr     = bitPtr | bitUintptr | bitUnsafePointer
)

// OperatorInfo represents an operator information.
type OperatorInfo struct {
	Lit      string
	InFirst  uint64       // first argument supported types.
	InSecond uint64       // second argument supported types. It may have SameAsFirst flag.
	Out      reflect.Kind // result type. It may be SameAsFirst.
}

var opInfos = [...]OperatorInfo{
	OpAdd:    {"+", bitsAllNumber | bitString | bitBigInt, bitSameAsFirst, SameAsFirst},
	OpSub:    {"-", bitsAllNumber | bitBigInt, bitSameAsFirst, SameAsFirst},
	OpMul:    {"*", bitsAllNumber | bitBigInt, bitSameAsFirst, SameAsFirst},
	OpQuo:    {"/", bitsAllNumber, bitSameAsFirst, SameAsFirst}, // NOTE: not include `bigint/bigint`
	OpMod:    {"%", bitsAllIntUint | bitBigInt, bitSameAsFirst, SameAsFirst},
	OpAnd:    {"&", bitsAllIntUint | bitBigInt, bitSameAsFirst, SameAsFirst},
	OpOr:     {"|", bitsAllIntUint | bitBigInt, bitSameAsFirst, SameAsFirst},
	OpXor:    {"^", bitsAllIntUint | bitBigInt, bitSameAsFirst, SameAsFirst},
	OpAndNot: {"&^", bitsAllIntUint | bitBigInt, bitSameAsFirst, SameAsFirst},
	OpLsh:    {"<<", bitsAllIntUint | bitBigInt, bitsAllIntUint, SameAsFirst},
	OpRsh:    {">>", bitsAllIntUint | bitBigInt, bitsAllIntUint, SameAsFirst},
	OpLT:     {"<", bitsAllReal | bitString | bitBigInt, bitSameAsFirst, Bool},
	OpLE:     {"<=", bitsAllReal | bitString | bitBigInt, bitSameAsFirst, Bool},
	OpGT:     {">", bitsAllReal | bitString | bitBigInt, bitSameAsFirst, Bool},
	OpGE:     {">=", bitsAllReal | bitString | bitBigInt, bitSameAsFirst, Bool},
	OpEQ:     {"==", bitsAllNumber | bitString | bitBigInt, bitSameAsFirst, Bool},
	OpEQNil:  {"== nil", bitUnsafePointer, bitNone, Bool},
	OpNE:     {"!=", bitsAllNumber | bitString | bitBigInt, bitSameAsFirst, Bool},
	OpNENil:  {"!= nil", bitUnsafePointer, bitNone, Bool},
	OpLAnd:   {"&&", bitBool, bitBool, Bool},
	OpLOr:    {"||", bitBool, bitBool, Bool},
	OpNeg:    {"-", bitsAllNumber | bitBigInt, bitNone, SameAsFirst},
	OpLNot:   {"!", bitBool, bitNone, Bool},
	OpBitNot: {"^", bitsAllIntUint | bitBigInt, bitNone, SameAsFirst},
}

// GetInfo returns the information of this operator.
func (op Operator) GetInfo() *OperatorInfo {
	return &opInfos[op]
}

func (op Operator) String() string {
	return opInfos[op].Lit
}

// -----------------------------------------------------------------------------

// AddrOperator type.
type AddrOperator Operator

const (
	// OpAddrVal `*addr`
	OpAddrVal = AddrOperator(0)
	// OpAddAssign `+=`
	OpAddAssign = AddrOperator(OpAdd)
	// OpSubAssign `-=`
	OpSubAssign = AddrOperator(OpSub)
	// OpMulAssign `*=`
	OpMulAssign = AddrOperator(OpMul)
	// OpQuoAssign `/=`
	OpQuoAssign = AddrOperator(OpQuo)
	// OpModAssign `%=`
	OpModAssign = AddrOperator(OpMod)

	// OpAndAssign '&='
	OpAndAssign = AddrOperator(OpAnd)
	// OpOrAssign '|='
	OpOrAssign = AddrOperator(OpOr)
	// OpXorAssign '^='
	OpXorAssign = AddrOperator(OpXor)
	// OpAndNotAssign '&^='
	OpAndNotAssign = AddrOperator(OpAndNot)
	// OpLshAssign '<<='
	OpLshAssign = AddrOperator(OpLsh)
	// OpRshAssign '>>='
	OpRshAssign = AddrOperator(OpRsh)
	// OpAssign `=`
	OpAssign AddrOperator = iota
	// OpInc '++'
	OpInc
	// OpDec '--'
	OpDec
)

// AddrOperatorInfo represents an addr-operator information.
type AddrOperatorInfo struct {
	Lit      string
	InFirst  uint64 // first argument supported types.
	InSecond uint64 // second argument supported types. It may have SameAsFirst flag.
}

var addropInfos = [...]AddrOperatorInfo{
	OpAddAssign:    {"+=", bitsAllNumber | bitString, bitSameAsFirst},
	OpSubAssign:    {"-=", bitsAllNumber, bitSameAsFirst},
	OpMulAssign:    {"*=", bitsAllNumber, bitSameAsFirst},
	OpQuoAssign:    {"/=", bitsAllNumber, bitSameAsFirst},
	OpModAssign:    {"%=", bitsAllIntUint, bitSameAsFirst},
	OpAndAssign:    {"&=", bitsAllIntUint, bitSameAsFirst},
	OpOrAssign:     {"|=", bitsAllIntUint, bitSameAsFirst},
	OpXorAssign:    {"^=", bitsAllIntUint, bitSameAsFirst},
	OpAndNotAssign: {"&^=", bitsAllIntUint, bitSameAsFirst},
	OpLshAssign:    {"<<=", bitsAllIntUint, bitsAllIntUint},
	OpRshAssign:    {">>=", bitsAllIntUint, bitsAllIntUint},
	OpInc:          {"++", bitsAllNumber, bitNone},
	OpDec:          {"--", bitsAllNumber, bitNone},
}

// GetInfo returns the information of this operator.
func (op AddrOperator) GetInfo() *AddrOperatorInfo {
	return &addropInfos[op]
}

func (op AddrOperator) String() string {
	switch op {
	case OpAddrVal:
		return "*"
	case OpAssign:
		return "="
	default:
		return addropInfos[op].Lit
	}
}

// -----------------------------------------------------------------------------

// GoBuiltin represents go builtin func.
type GoBuiltin uint

func (p GoBuiltin) String() string {
	return goBuiltinNames[p]
}

const (
	gobInvalid GoBuiltin = iota
	// GobLen - len: 1
	GobLen
	// GobCap - cap: 2
	GobCap
	// GobCopy - copy: 3
	GobCopy
	// GobDelete - delete: 4
	GobDelete
	// GobComplex - complex: 5
	GobComplex
	// GobReal - real: 6
	GobReal
	// GobImag - imag: 7
	GobImag
	// GobClose - close: 8
	GobClose
)

var goBuiltinNames = [...]string{
	GobLen:     "len",
	GobCap:     "cap",
	GobCopy:    "copy",
	GobDelete:  "delete",
	GobComplex: "complex",
	GobReal:    "real",
	GobImag:    "imag",
	GobClose:   "close",
}

// -----------------------------------------------------------------------------

// Operator related constants, for Operator/AddrOperator instr.
const (
	// BitNone - bitNone
	BitNone = bitNone
	// BitsAllIntUint - bitsAllIntUint
	BitsAllIntUint = bitsAllIntUint
)

// -----------------------------------------------------------------------------

// Slice related constants, for Slice/Slice3 instr.
const (
	// SliceConstIndexLast - slice const index max
	SliceConstIndexLast = (1 << 13) - 3
	// SliceDefaultIndex - unspecified index
	SliceDefaultIndex = -2
)

// -----------------------------------------------------------------------------
<commit_msg>exec.spec: addropInfos add BigInt<commit_after>/*
 Copyright 2020 The GoPlus Authors (goplus.org)

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/

package exec

import (
	"reflect"
)

// -----------------------------------------------------------------------------

// Operator type.
type Operator uint

const (
	// OpInvalid - invalid operator
	OpInvalid Operator = iota
	// OpAdd '+' String/Int/Uint/Float/Complex
	OpAdd
	// OpSub '-' Int/Uint/Float/Complex
	OpSub
	// OpMul '*' Int/Uint/Float/Complex
	OpMul
	// OpQuo '/' Int/Uint/Float/Complex
	OpQuo
	// OpMod '%' Int/Uint
	OpMod
	// OpAnd '&' Int/Uint
	OpAnd
	// OpOr '|' Int/Uint
	OpOr
	// OpXor '^' Int/Uint
	OpXor
	// OpAndNot '&^' Int/Uint
	OpAndNot
	// OpLsh '<<' Int/Uint, Uint
	OpLsh
	// OpRsh '>>' Int/Uint, Uint
	OpRsh
	// OpLT '<' String/Int/Uint/Float
	OpLT
	// OpLE '<=' String/Int/Uint/Float
	OpLE
	// OpGT '>' String/Int/Uint/Float
	OpGT
	// OpGE '>=' String/Int/Uint/Float
	OpGE
	// OpEQ '==' ComparableType
	// Slice, map, and function values are not comparable. However, as a special case, a slice, map,
	// or function value may be compared to the predeclared identifier nil.
	OpEQ
	// OpEQNil '==' nil
	OpEQNil
	// OpNE '!=' ComparableType
	OpNE
	// OpNENil '!=' nil
	OpNENil
	// OpLAnd '&&' Bool
	OpLAnd
	// OpLOr '||' Bool
	OpLOr
	// OpLNot '!'
	OpLNot
	// OpNeg '-'
	OpNeg
	// OpBitNot '^'
	OpBitNot
)

const (
	// SameAsFirst means the second argument is same as first argument type.
	SameAsFirst = reflect.Invalid
)

const (
	bitNone          = 0
	bitSameAsFirst   = 1 << SameAsFirst
	bitBool          = 1 << Bool
	bitInt           = 1 << Int
	bitInt8          = 1 << Int8
	bitInt16         = 1 << Int16
	bitInt32         = 1 << Int32
	bitInt64         = 1 << Int64
	bitUint          = 1 << Uint
	bitUint8         = 1 << Uint8
	bitUint16        = 1 << Uint16
	bitUint32        = 1 << Uint32
	bitUint64        = 1 << Uint64
	bitUintptr       = 1 << Uintptr
	bitFloat32       = 1 << Float32
	bitFloat64       = 1 << Float64
	bitComplex64     = 1 << Complex64
	bitComplex128    = 1 << Complex128
	bitString        = 1 << String
	bitUnsafePointer = 1 << UnsafePointer
	bitPtr           = 1 << reflect.Ptr
	bitBigInt        = 1 << BigInt
	bitBigRat        = 1 << BigRat
	bitBigFloat      = 1 << BigFloat

	bitsAllInt     = bitInt | bitInt8 | bitInt16 | bitInt32 | bitInt64
	bitsAllUint    = bitUint | bitUint8 | bitUint16 | bitUint32 | bitUint64 | bitUintptr
	bitsAllIntUint = bitsAllInt | bitsAllUint
	bitsAllFloat   = bitFloat32 | bitFloat64
	bitsAllReal    = bitsAllIntUint | bitsAllFloat | bitBigRat | bitBigFloat
	bitsAllComplex = bitComplex64 | bitComplex128
	bitsAllNumber  = bitsAllReal | bitsAllComplex
	bitsAllPtr     = bitPtr | bitUintptr | bitUnsafePointer
)

// OperatorInfo represents an operator information.
type OperatorInfo struct {
	Lit      string
	InFirst  uint64       // first argument supported types.
	InSecond uint64       // second argument supported types. It may have SameAsFirst flag.
	Out      reflect.Kind // result type. It may be SameAsFirst.
}

var opInfos = [...]OperatorInfo{
	OpAdd:    {"+", bitsAllNumber | bitString | bitBigInt, bitSameAsFirst, SameAsFirst},
	OpSub:    {"-", bitsAllNumber | bitBigInt, bitSameAsFirst, SameAsFirst},
	OpMul:    {"*", bitsAllNumber | bitBigInt, bitSameAsFirst, SameAsFirst},
	OpQuo:    {"/", bitsAllNumber, bitSameAsFirst, SameAsFirst}, // NOTE: not include `bigint/bigint`
	OpMod:    {"%", bitsAllIntUint | bitBigInt, bitSameAsFirst, SameAsFirst},
	OpAnd:    {"&", bitsAllIntUint | bitBigInt, bitSameAsFirst, SameAsFirst},
	OpOr:     {"|", bitsAllIntUint | bitBigInt, bitSameAsFirst, SameAsFirst},
	OpXor:    {"^", bitsAllIntUint | bitBigInt, bitSameAsFirst, SameAsFirst},
	OpAndNot: {"&^", bitsAllIntUint | bitBigInt, bitSameAsFirst, SameAsFirst},
	OpLsh:    {"<<", bitsAllIntUint | bitBigInt, bitsAllIntUint, SameAsFirst},
	OpRsh:    {">>", bitsAllIntUint | bitBigInt, bitsAllIntUint, SameAsFirst},
	OpLT:     {"<", bitsAllReal | bitString | bitBigInt, bitSameAsFirst, Bool},
	OpLE:     {"<=", bitsAllReal | bitString | bitBigInt, bitSameAsFirst, Bool},
	OpGT:     {">", bitsAllReal | bitString | bitBigInt, bitSameAsFirst, Bool},
	OpGE:     {">=", bitsAllReal | bitString | bitBigInt, bitSameAsFirst, Bool},
	OpEQ:     {"==", bitsAllNumber | bitString | bitBigInt, bitSameAsFirst, Bool},
	OpEQNil:  {"== nil", bitUnsafePointer, bitNone, Bool},
	OpNE:     {"!=", bitsAllNumber | bitString | bitBigInt, bitSameAsFirst, Bool},
	OpNENil:  {"!= nil", bitUnsafePointer, bitNone, Bool},
	OpLAnd:   {"&&", bitBool, bitBool, Bool},
	OpLOr:    {"||", bitBool, bitBool, Bool},
	OpNeg:    {"-", bitsAllNumber | bitBigInt, bitNone, SameAsFirst},
	OpLNot:   {"!", bitBool, bitNone, Bool},
	OpBitNot: {"^", bitsAllIntUint | bitBigInt, bitNone, SameAsFirst},
}

// GetInfo returns the information of this operator.
func (op Operator) GetInfo() *OperatorInfo {
	return &opInfos[op]
}

func (op Operator) String() string {
	return opInfos[op].Lit
}

// -----------------------------------------------------------------------------

// AddrOperator type.
type AddrOperator Operator

const (
	// OpAddrVal `*addr`
	OpAddrVal = AddrOperator(0)
	// OpAddAssign `+=`
	OpAddAssign = AddrOperator(OpAdd)
	// OpSubAssign `-=`
	OpSubAssign = AddrOperator(OpSub)
	// OpMulAssign `*=`
	OpMulAssign = AddrOperator(OpMul)
	// OpQuoAssign `/=`
	OpQuoAssign = AddrOperator(OpQuo)
	// OpModAssign `%=`
	OpModAssign = AddrOperator(OpMod)

	// OpAndAssign '&='
	OpAndAssign = AddrOperator(OpAnd)
	// OpOrAssign '|='
	OpOrAssign = AddrOperator(OpOr)
	// OpXorAssign '^='
	OpXorAssign = AddrOperator(OpXor)
	// OpAndNotAssign '&^='
	OpAndNotAssign = AddrOperator(OpAndNot)
	// OpLshAssign '<<='
	OpLshAssign = AddrOperator(OpLsh)
	// OpRshAssign '>>='
	OpRshAssign = AddrOperator(OpRsh)
	// OpAssign `=`
	OpAssign AddrOperator = iota
	// OpInc '++'
	OpInc
	// OpDec '--'
	OpDec
)

// AddrOperatorInfo represents an addr-operator information.
type AddrOperatorInfo struct {
	Lit      string
	InFirst  uint64 // first argument supported types.
	InSecond uint64 // second argument supported types. It may have SameAsFirst flag.
}

var addropInfos = [...]AddrOperatorInfo{
	OpAddAssign:    {"+=", bitsAllNumber | bitString | bitBigInt, bitSameAsFirst},
	OpSubAssign:    {"-=", bitsAllNumber | bitBigInt, bitSameAsFirst},
	OpMulAssign:    {"*=", bitsAllNumber | bitBigInt, bitSameAsFirst},
	OpQuoAssign:    {"/=", bitsAllNumber | bitBigInt, bitSameAsFirst},
	OpModAssign:    {"%=", bitsAllIntUint, bitSameAsFirst},
	OpAndAssign:    {"&=", bitsAllIntUint, bitSameAsFirst},
	OpOrAssign:     {"|=", bitsAllIntUint, bitSameAsFirst},
	OpXorAssign:    {"^=", bitsAllIntUint, bitSameAsFirst},
	OpAndNotAssign: {"&^=", bitsAllIntUint, bitSameAsFirst},
	OpLshAssign:    {"<<=", bitsAllIntUint, bitsAllIntUint},
	OpRshAssign:    {">>=", bitsAllIntUint, bitsAllIntUint},
	OpInc:          {"++", bitsAllNumber | bitBigInt, bitNone},
	OpDec:          {"--", bitsAllNumber | bitBigInt, bitNone},
}

// GetInfo returns the information of this operator.
func (op AddrOperator) GetInfo() *AddrOperatorInfo {
	return &addropInfos[op]
}

func (op AddrOperator) String() string {
	switch op {
	case OpAddrVal:
		return "*"
	case OpAssign:
		return "="
	default:
		return addropInfos[op].Lit
	}
}

// -----------------------------------------------------------------------------

// GoBuiltin represents go builtin func.
type GoBuiltin uint

func (p GoBuiltin) String() string {
	return goBuiltinNames[p]
}

const (
	gobInvalid GoBuiltin = iota
	// GobLen - len: 1
	GobLen
	// GobCap - cap: 2
	GobCap
	// GobCopy - copy: 3
	GobCopy
	// GobDelete - delete: 4
	GobDelete
	// GobComplex - complex: 5
	GobComplex
	// GobReal - real: 6
	GobReal
	// GobImag - imag: 7
	GobImag
	// GobClose - close: 8
	GobClose
)

var goBuiltinNames = [...]string{
	GobLen:     "len",
	GobCap:     "cap",
	GobCopy:    "copy",
	GobDelete:  "delete",
	GobComplex: "complex",
	GobReal:    "real",
	GobImag:    "imag",
	GobClose:   "close",
}

// -----------------------------------------------------------------------------

// Operator related constants, for Operator/AddrOperator instr.
const (
	// BitNone - bitNone
	BitNone = bitNone
	// BitsAllIntUint - bitsAllIntUint
	BitsAllIntUint = bitsAllIntUint
)

// -----------------------------------------------------------------------------

// Slice related constants, for Slice/Slice3 instr.
const (
	// SliceConstIndexLast - slice const index max
	SliceConstIndexLast = (1 << 13) - 3
	// SliceDefaultIndex - unspecified index
	SliceDefaultIndex = -2
)

// -----------------------------------------------------------------------------
<|endoftext|>


<commit_before>/*package shellfish contains code for computing the splashback shells of
halos in N-body simulations.*/
package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"strings"

	"github.com/phil-mansfield/shellfish/cmd"
	"github.com/phil-mansfield/shellfish/cmd/env"
	"github.com/phil-mansfield/shellfish/version"
)

var helpStrings = map[string]string{
	"setup": `The setup mode isn't implemented yet.`,
	"id":    `Mode specifcations will be documented in version 0.3.0.`,
	"tree":  `Mode specifcations will be documented in version 0.3.0.`,
	"coord": `Mode specifcations will be documented in version 0.3.0.`,
	"shell": `Mode specifcations will be documented in version 0.3.0.`,
	"stats": `Mode specifcations will be documented in version 0.3.0.`,

	"config":       new(cmd.GlobalConfig).ExampleConfig(),
	"setup.config": `The setup mode does not have a non-global config file.`,
	"id.config":    cmd.ModeNames["id"].ExampleConfig(),
	"tree.config":  `The tree mode does not have a non-global config file.`,
	"coord.config": `The coord mode does not have a non-global config file.`,
	"shell.config": cmd.ModeNames["shell"].ExampleConfig(),
	"stats.config": cmd.ModeNames["stats"].ExampleConfig(),
}

var modeDescriptions = `My help modes are:
shellfish help
shellfish help [ setup | id | tree | coord | shell | stats ]
shellfish help [ config | id.config | shell.config | stats.config ]

My setup mode is:
shellfish setup ____.config

My analysis modes are:
shellfish id     [flags] ____.config [____.id.config]
shellfish tree ____.config
shellfish coord ____.config
shellfish shell  [flags] ____.config [____.shell.config]
shellfish stats  [flags] ____.config [____.stats.config]`

func main() {
	args := os.Args
	if len(args) <= 1 {
		fmt.Fprintf(
			os.Stderr, "I was not supplied with a mode.\nFor help, type "+
				"'./shellfish help'.\n",
		)
		os.Exit(1)
	}

	if args[1] == "help" {
		switch len(args) - 2 {
		case 0:
			fmt.Println(modeDescriptions)
		case 1:
			text, ok := helpStrings[args[2]]
			if !ok {
				fmt.Printf("I don't recognize the help target '%s'\n", args[2])
			} else {
				fmt.Println(text)
			}
		case 2:
			fmt.Println("The help mode can only take a single argument.")
		}
		os.Exit(0)
		// TODO: Implement the help command.
	} else if args[1] == "version" {
		fmt.Printf("Shellfish version %s\n", version.SourceVersion)
		os.Exit(0)
	}

	mode, ok := cmd.ModeNames[args[1]]
	if !ok {
		fmt.Fprintf(
			os.Stderr, "You passed me the mode '%s', which I don't "+
				"recognize.\nFor help, type './shellfish help'\n", args[1],
		)
		fmt.Println("Shellfish terminating.")
		os.Exit(1)
	}

	var lines []string
	switch args[1] {
	case "tree", "coord", "shell", "stats":
		var err error
		lines, err = stdinLines()
		if err != nil {
			fmt.Fprintf(os.Stderr, err.Error())
			fmt.Println("Shellfish terminating.")
			os.Exit(1)
		}

		if len(lines) == 0 {
			return
		} else if len(lines) == 1 && len(lines[0]) >= 9 &&
			lines[0][:9] == "Shellfish" {
			fmt.Println(lines[0])
			os.Exit(1)
		}
	}

	flags := getFlags(args)
	config, ok := getConfig(args)
	gConfigName, gConfig, err := getGlobalConfig(args)
	if err != nil {
		log.Printf("Error running mode %s:\n%s\n", args[1], err.Error())
		fmt.Println("Shellfish terminating.")
		os.Exit(1)
	}

	if ok {
		if err = mode.ReadConfig(config); err != nil {
			log.Printf("Error running mode %s:\n%s\n", args[1], err.Error())
			fmt.Println("Shellfish terminating.")
			os.Exit(1)
		}
	} else {
		if err = mode.ReadConfig(""); err != nil {
			log.Printf("Error running mode %s:\n%s\n", args[1], err.Error())
			fmt.Println("Shellfish terminating.")
			os.Exit(1)
		}
	}

	if err = checkMemoDir(gConfig.MemoDir, gConfigName); err != nil {
		log.Printf("Error running mode %s:\n%s\n", args[1], err.Error())
		fmt.Println("Shellfish terminating.")
		os.Exit(1)
	}

	e := &env.Environment{MemoDir: gConfig.MemoDir}
	err = initCatalogs(gConfig, e)
	if err != nil {
		log.Printf("Error running mode %s:\n%s\n", args[1], err.Error())
		fmt.Println("Shellfish terminating.")
		os.Exit(1)
	}
	err = initHalos(args[1], gConfig, e)
	if err != nil {
		log.Printf("Error running mode %s:\n%s\n", args[1], err.Error())
		fmt.Println("Shellfish terminating.")
		os.Exit(1)
	}

	out, err := mode.Run(flags, gConfig, e, lines)
	if err != nil {
		log.Printf("Error running mode %s:\n%s\n", args[1], err.Error())
		fmt.Println("Shellfish terminating.")
		os.Exit(1)
	}

	for i := range out {
		fmt.Println(out[i])
	}
}

// stdinLines reads stdin and splits it into lines.
func stdinLines() ([]string, error) {
	bs, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		return nil, fmt.Errorf(
			"Error reading stdin: %s.", err.Error(),
		)
	}
	text := string(bs)
	lines := strings.Split(text, "\n")
	if lines[len(lines)-1] == "" {
		lines = lines[:len(lines)-1]
	}
	return lines, nil
}

// getFlags reutrns the flag tokens from the command line arguments.
func getFlags(args []string) []string {
	return args[1 : len(args)-1-configNum(args)]
}

// getGlobalConfig returns the name of the base config file from the command
// line arguments.
func getGlobalConfig(args []string) (string, *cmd.GlobalConfig, error) {
	name := os.Getenv("SHELLFISH_GLOBAL_CONFIG")
	if name != "" {
		if configNum(args) > 1 {
			return "", nil, fmt.Errorf("$SHELLFISH_GLOBAL_CONFIG has been " +
				"set, so you may only pass a single config file as a " +
				"parameter.")
		}

		config := &cmd.GlobalConfig{}
		err := config.ReadConfig(name)
		if err != nil {
			return "", nil, err
		}
		return name, config, nil
	}

	switch configNum(args) {
	case 0:
		return "", nil, fmt.Errorf("No config files provided in command " +
			"line arguments.")
	case 1:
		name = args[len(args)-1]
	case 2:
		name = args[len(args)-2]
	default:
		return "", nil, fmt.Errorf("Passed too many config files as arguments.")
	}

	config := &cmd.GlobalConfig{}
	err := config.ReadConfig(name)
	if err != nil {
		return "", nil, err
	}
	return name, config, nil
}

// getConfig return the name of the mode-specific config file from the command
// line arguments.
func getConfig(args []string) (string, bool) {
	if os.Getenv("SHELLFISH_GLOBAL_CONFIG") != "" && configNum(args) == 1 {
		return args[len(args)-1], true
	} else if os.Getenv("SHELLFISH_GLOBAL_CONFIG") == "" &&
		configNum(args) == 2 {

		return args[len(args)-1], true
	}
	return "", false
}

// configNum returns the number of configuration files at the end of the
// argument list (up to 2).
func configNum(args []string) int {
	num := 0
	for i := len(args) - 1; i >= 0; i-- {
		if isConfig(args[i]) {
			num++
		} else {
			break
		}
	}
	return num
}

// isConfig returns true if the fiven string is a config file name.
func isConfig(s string) bool {
	return len(s) >= 7 && s[len(s)-7:] == ".config"
}

// cehckMemoDir checks whether the given MemoDir corresponds to a GlobalConfig
// file with the exact same variables. If not, a non-nil error is returned.
// If the MemoDir does not have an associated GlobalConfig file, the current
// one will be copied in.
func checkMemoDir(memoDir, configFile string) error {
	memoConfigFile := path.Join(memoDir, "memo.config")

	if _, err := os.Stat(memoConfigFile); err != nil {
		// File doesn't exist, directory is clean.
		err = copyFile(memoConfigFile, configFile)
		return err
	}

	config, memoConfig := &cmd.GlobalConfig{}, &cmd.GlobalConfig{}
	if err := config.ReadConfig(configFile); err != nil {
		return err
	}
	if err := memoConfig.ReadConfig(memoConfigFile); err != nil {
		return err
	}

	if !configEqual(config, memoConfig) {
		return fmt.Errorf("The variables in the config file '%s' do not "+
			"match the varables used when creating the MemoDir, '%s.' These "+
			"variables can be compared by inspecting '%s' and '%s'",
			configFile, memoDir, configFile, memoConfigFile,
		)
	}
	return nil
}

// copyFile copies a file from src to dst.
func copyFile(dst, src string) error {
	srcFile, err := os.Open(src)
	if err != nil {
		return err
	}
	defer srcFile.Close()

	dstFile, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer dstFile.Close()

	if _, err = io.Copy(dstFile, srcFile); err != nil {
		return err
	}
	return dstFile.Sync()
}

func configEqual(m, c *cmd.GlobalConfig) bool {
	// Well, equal up to the variables that actually matter.
	// (i.e. changing something like Threads shouldn't flush the memoization
	// buffer. Otherwise, I'd just use reflection.)
	return c.Version == m.Version &&
		c.SnapshotFormat == m.SnapshotFormat &&
		c.SnapshotType == m.SnapshotType &&
		c.HaloDir == m.HaloDir &&
		c.HaloType == m.HaloType &&
		c.TreeDir == m.TreeDir &&
		c.MemoDir == m.MemoDir && // (this is impossible)
		int64sEqual(c.BlockMins, m.BlockMins) &&
		int64sEqual(c.BlockMaxes, m.BlockMaxes) &&
		c.SnapMin == m.SnapMin &&
		c.SnapMax == m.SnapMax &&
		stringsEqual(c.SnapshotFormatMeanings, m.SnapshotFormatMeanings) &&
		c.HaloPositionUnits == m.HaloPositionUnits &&
		c.HaloMassUnits == m.HaloMassUnits &&
		c.HaloIDColumn == m.HaloIDColumn &&
		c.HaloM200mColumn == m.HaloM200mColumn &&
		int64sEqual(c.HaloPositionColumns, m.HaloPositionColumns) &&
		c.Endianness == m.Endianness
}

func int64sEqual(xs, ys []int64) bool {
	if len(xs) != len(ys) {
		return false
	}
	for i := range xs {
		if xs[i] != ys[i] {
			return false
		}
	}
	return true
}

func stringsEqual(xs, ys []string) bool {
	if len(xs) != len(ys) {
		return false
	}
	for i := range xs {
		if xs[i] != ys[i] {
			return false
		}
	}
	return true
}

func initHalos(
	mode string, gConfig *cmd.GlobalConfig, e *env.Environment,
) error {
	switch mode {
	case "shell", "stats":
		return nil
	}

	switch gConfig.HaloType {
	case "nil":
		return fmt.Errorf("You may not use nil as a HaloType for the "+
			"mode '%s.'\n", mode)
	case "Text":
		return e.InitTextHalo(&gConfig.HaloInfo)
		if gConfig.TreeType != "consistent-trees" {
			return fmt.Errorf("You're trying to use the '%s' TreeType with " +
				"the 'Text' HaloType.")
		}
	}
	if gConfig.TreeType == "nil" {
		return fmt.Errorf("You may not use nil as a TreeType for the "+
			"mode '%s.'\n", mode)
	}

	panic("Impossible")
}

func initCatalogs(gConfig *cmd.GlobalConfig, e *env.Environment) error {
	switch gConfig.SnapshotType {
	case "gotetra":
		return e.InitGotetra(&gConfig.ParticleInfo, gConfig.ValidateFormats)
	case "LGadget-2":
		return e.InitLGadget2(&gConfig.ParticleInfo, gConfig.ValidateFormats)
	case "ARTIO":
		return e.InitARTIO(&gConfig.ParticleInfo, gConfig.ValidateFormats)
	}
	panic("Impossible.")
}
<commit_msg>Small updates to help mode.<commit_after>/*package shellfish contains code for computing the splashback shells of
halos in N-body simulations.*/
package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path"
	"strings"

	"github.com/phil-mansfield/shellfish/cmd"
	"github.com/phil-mansfield/shellfish/cmd/env"
	"github.com/phil-mansfield/shellfish/version"
)

var helpStrings = map[string]string{
	"setup": `The setup mode isn't implemented yet.`,
	"id":    `Mode specifcations will be documented in version 0.3.0.`,
	"tree":  `Mode specifcations will be documented in version 0.3.0.`,
	"coord": `Mode specifcations will be documented in version 0.3.0.`,
	"shell": `Mode specifcations will be documented in version 0.3.0.`,
	"stats": `Mode specifcations will be documented in version 0.3.0.`,

	"config":       new(cmd.GlobalConfig).ExampleConfig(),
	"setup.config": `The setup mode does not have a non-global config file.`,
	"id.config":    cmd.ModeNames["id"].ExampleConfig(),
	"tree.config":  cmd.ModeNames["tree"].ExampleConfig(),
	"coord.config": `The coord mode does not have a non-global config file.`,
	"shell.config": cmd.ModeNames["shell"].ExampleConfig(),
	"stats.config": cmd.ModeNames["stats"].ExampleConfig(),
}

var modeDescriptions = `My help modes are:
shellfish help
shellfish help [ setup | id | tree | coord | shell | stats ]
shellfish help [ config | id.config | shell.config | stats.config ]

My setup mode is:
shellfish setup ____.config

My analysis modes are:
shellfish id     [flags] ____.config [____.id.config]
shellfish tree ____.config [____.tree.config]
shellfish coord ____.config
shellfish shell  [flags] ____.config [____.shell.config]
shellfish stats  [flags] ____.config [____.stats.config]`

func main() {
	args := os.Args
	if len(args) <= 1 {
		fmt.Fprintf(
			os.Stderr, "I was not supplied with a mode.\nFor help, type "+
				"'./shellfish help'.\n",
		)
		os.Exit(1)
	}

	if args[1] == "help" {
		switch len(args) - 2 {
		case 0:
			fmt.Println(modeDescriptions)
		case 1:
			text, ok := helpStrings[args[2]]
			if !ok {
				fmt.Printf("I don't recognize the help target '%s'\n", args[2])
			} else {
				fmt.Println(text)
			}
		case 2:
			fmt.Println("The help mode can only take a single argument.")
		}
		os.Exit(0)
		// TODO: Implement the help command.
	} else if args[1] == "version" {
		fmt.Printf("Shellfish version %s\n", version.SourceVersion)
		os.Exit(0)
	}

	mode, ok := cmd.ModeNames[args[1]]
	if !ok {
		fmt.Fprintf(
			os.Stderr, "You passed me the mode '%s', which I don't "+
				"recognize.\nFor help, type './shellfish help'\n", args[1],
		)
		fmt.Println("Shellfish terminating.")
		os.Exit(1)
	}

	var lines []string
	switch args[1] {
	case "tree", "coord", "shell", "stats":
		var err error
		lines, err = stdinLines()
		if err != nil {
			fmt.Fprintf(os.Stderr, err.Error())
			fmt.Println("Shellfish terminating.")
			os.Exit(1)
		}

		if len(lines) == 0 {
			return
		} else if len(lines) == 1 && len(lines[0]) >= 9 &&
			lines[0][:9] == "Shellfish" {
			fmt.Println(lines[0])
			os.Exit(1)
		}
	}

	flags := getFlags(args)
	config, ok := getConfig(args)
	gConfigName, gConfig, err := getGlobalConfig(args)
	if err != nil {
		log.Printf("Error running mode %s:\n%s\n", args[1], err.Error())
		fmt.Println("Shellfish terminating.")
		os.Exit(1)
	}

	if ok {
		if err = mode.ReadConfig(config); err != nil {
			log.Printf("Error running mode %s:\n%s\n", args[1], err.Error())
			fmt.Println("Shellfish terminating.")
			os.Exit(1)
		}
	} else {
		if err = mode.ReadConfig(""); err != nil {
			log.Printf("Error running mode %s:\n%s\n", args[1], err.Error())
			fmt.Println("Shellfish terminating.")
			os.Exit(1)
		}
	}

	if err = checkMemoDir(gConfig.MemoDir, gConfigName); err != nil {
		log.Printf("Error running mode %s:\n%s\n", args[1], err.Error())
		fmt.Println("Shellfish terminating.")
		os.Exit(1)
	}

	e := &env.Environment{MemoDir: gConfig.MemoDir}
	err = initCatalogs(gConfig, e)
	if err != nil {
		log.Printf("Error running mode %s:\n%s\n", args[1], err.Error())
		fmt.Println("Shellfish terminating.")
		os.Exit(1)
	}
	err = initHalos(args[1], gConfig, e)
	if err != nil {
		log.Printf("Error running mode %s:\n%s\n", args[1], err.Error())
		fmt.Println("Shellfish terminating.")
		os.Exit(1)
	}

	out, err := mode.Run(flags, gConfig, e, lines)
	if err != nil {
		log.Printf("Error running mode %s:\n%s\n", args[1], err.Error())
		fmt.Println("Shellfish terminating.")
		os.Exit(1)
	}

	for i := range out {
		fmt.Println(out[i])
	}
}

// stdinLines reads stdin and splits it into lines.
func stdinLines() ([]string, error) {
	bs, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		return nil, fmt.Errorf(
			"Error reading stdin: %s.", err.Error(),
		)
	}
	text := string(bs)
	lines := strings.Split(text, "\n")
	if lines[len(lines)-1] == "" {
		lines = lines[:len(lines)-1]
	}
	return lines, nil
}

// getFlags reutrns the flag tokens from the command line arguments.
func getFlags(args []string) []string {
	return args[1 : len(args)-1-configNum(args)]
}

// getGlobalConfig returns the name of the base config file from the command
// line arguments.
func getGlobalConfig(args []string) (string, *cmd.GlobalConfig, error) {
	name := os.Getenv("SHELLFISH_GLOBAL_CONFIG")
	if name != "" {
		if configNum(args) > 1 {
			return "", nil, fmt.Errorf("$SHELLFISH_GLOBAL_CONFIG has been " +
				"set, so you may only pass a single config file as a " +
				"parameter.")
		}

		config := &cmd.GlobalConfig{}
		err := config.ReadConfig(name)
		if err != nil {
			return "", nil, err
		}
		return name, config, nil
	}

	switch configNum(args) {
	case 0:
		return "", nil, fmt.Errorf("No config files provided in command " +
			"line arguments.")
	case 1:
		name = args[len(args)-1]
	case 2:
		name = args[len(args)-2]
	default:
		return "", nil, fmt.Errorf("Passed too many config files as arguments.")
	}

	config := &cmd.GlobalConfig{}
	err := config.ReadConfig(name)
	if err != nil {
		return "", nil, err
	}
	return name, config, nil
}

// getConfig return the name of the mode-specific config file from the command
// line arguments.
func getConfig(args []string) (string, bool) {
	if os.Getenv("SHELLFISH_GLOBAL_CONFIG") != "" && configNum(args) == 1 {
		return args[len(args)-1], true
	} else if os.Getenv("SHELLFISH_GLOBAL_CONFIG") == "" &&
		configNum(args) == 2 {

		return args[len(args)-1], true
	}
	return "", false
}

// configNum returns the number of configuration files at the end of the
// argument list (up to 2).
func configNum(args []string) int {
	num := 0
	for i := len(args) - 1; i >= 0; i-- {
		if isConfig(args[i]) {
			num++
		} else {
			break
		}
	}
	return num
}

// isConfig returns true if the fiven string is a config file name.
func isConfig(s string) bool {
	return len(s) >= 7 && s[len(s)-7:] == ".config"
}

// cehckMemoDir checks whether the given MemoDir corresponds to a GlobalConfig
// file with the exact same variables. If not, a non-nil error is returned.
// If the MemoDir does not have an associated GlobalConfig file, the current
// one will be copied in.
func checkMemoDir(memoDir, configFile string) error {
	memoConfigFile := path.Join(memoDir, "memo.config")

	if _, err := os.Stat(memoConfigFile); err != nil {
		// File doesn't exist, directory is clean.
		err = copyFile(memoConfigFile, configFile)
		return err
	}

	config, memoConfig := &cmd.GlobalConfig{}, &cmd.GlobalConfig{}
	if err := config.ReadConfig(configFile); err != nil {
		return err
	}
	if err := memoConfig.ReadConfig(memoConfigFile); err != nil {
		return err
	}

	if !configEqual(config, memoConfig) {
		return fmt.Errorf("The variables in the config file '%s' do not "+
			"match the varables used when creating the MemoDir, '%s.' These "+
			"variables can be compared by inspecting '%s' and '%s'",
			configFile, memoDir, configFile, memoConfigFile,
		)
	}
	return nil
}

// copyFile copies a file from src to dst.
func copyFile(dst, src string) error {
	srcFile, err := os.Open(src)
	if err != nil {
		return err
	}
	defer srcFile.Close()

	dstFile, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer dstFile.Close()

	if _, err = io.Copy(dstFile, srcFile); err != nil {
		return err
	}
	return dstFile.Sync()
}

func configEqual(m, c *cmd.GlobalConfig) bool {
	// Well, equal up to the variables that actually matter.
	// (i.e. changing something like Threads shouldn't flush the memoization
	// buffer. Otherwise, I'd just use reflection.)
	return c.Version == m.Version &&
		c.SnapshotFormat == m.SnapshotFormat &&
		c.SnapshotType == m.SnapshotType &&
		c.HaloDir == m.HaloDir &&
		c.HaloType == m.HaloType &&
		c.TreeDir == m.TreeDir &&
		c.MemoDir == m.MemoDir && // (this is impossible)
		int64sEqual(c.BlockMins, m.BlockMins) &&
		int64sEqual(c.BlockMaxes, m.BlockMaxes) &&
		c.SnapMin == m.SnapMin &&
		c.SnapMax == m.SnapMax &&
		stringsEqual(c.SnapshotFormatMeanings, m.SnapshotFormatMeanings) &&
		c.HaloPositionUnits == m.HaloPositionUnits &&
		c.HaloMassUnits == m.HaloMassUnits &&
		c.HaloIDColumn == m.HaloIDColumn &&
		c.HaloM200mColumn == m.HaloM200mColumn &&
		int64sEqual(c.HaloPositionColumns, m.HaloPositionColumns) &&
		c.Endianness == m.Endianness
}

func int64sEqual(xs, ys []int64) bool {
	if len(xs) != len(ys) {
		return false
	}
	for i := range xs {
		if xs[i] != ys[i] {
			return false
		}
	}
	return true
}

func stringsEqual(xs, ys []string) bool {
	if len(xs) != len(ys) {
		return false
	}
	for i := range xs {
		if xs[i] != ys[i] {
			return false
		}
	}
	return true
}

func initHalos(
	mode string, gConfig *cmd.GlobalConfig, e *env.Environment,
) error {
	switch mode {
	case "shell", "stats":
		return nil
	}

	switch gConfig.HaloType {
	case "nil":
		return fmt.Errorf("You may not use nil as a HaloType for the "+
			"mode '%s.'\n", mode)
	case "Text":
		return e.InitTextHalo(&gConfig.HaloInfo)
		if gConfig.TreeType != "consistent-trees" {
			return fmt.Errorf("You're trying to use the '%s' TreeType with " +
				"the 'Text' HaloType.")
		}
	}
	if gConfig.TreeType == "nil" {
		return fmt.Errorf("You may not use nil as a TreeType for the "+
			"mode '%s.'\n", mode)
	}

	panic("Impossible")
}

func initCatalogs(gConfig *cmd.GlobalConfig, e *env.Environment) error {
	switch gConfig.SnapshotType {
	case "gotetra":
		return e.InitGotetra(&gConfig.ParticleInfo, gConfig.ValidateFormats)
	case "LGadget-2":
		return e.InitLGadget2(&gConfig.ParticleInfo, gConfig.ValidateFormats)
	case "ARTIO":
		return e.InitARTIO(&gConfig.ParticleInfo, gConfig.ValidateFormats)
	}
	panic("Impossible.")
}
<|endoftext|>


<commit_before>package couchdb

import (
	"encoding/json"
	"fmt"
	"net/http"
)

// This file contains error handling code for couchdb request
// Possible errors in connecting to couchdb
// 503 Service Unavailable when the stack cant connect to couchdb or when
// 		 couchdb response is interrupted mid-stream
// 500 When the viper provided configuration does not allow us to properly
// 		 call http.newRequest, ie. wrong couchdbURL config

// Possible native couchdb errors
// 400 Bad Request : Bad request structure. The error can indicate an error
// 		with the request URL, path or headers. Differences in the supplied MD5
// 		hash and content also trigger this error, as this may indicate message
// 		corruption.
// 401 Unauthorized : The item requested was not available using the supplied
// 		authorization, or authorization was not supplied.
// 		{"error":"unauthorized","reason":"You are not a server admin."}
// 		{"error":"unauthorized","reason":"Name or password is incorrect."}
// 403 Forbidden : The requested item or operation is forbidden.
// 404 Not Found : The requested content could not be found. The content will
// 		include further information, as a JSON object, if available.
// 		**The structure will contain two keys, error and reason.**
//    {"error":"not_found","reason":"deleted"}
//    {"error":"not_found","reason":"missing"}
//    {"error":"not_found","reason":"no_db_file"}
// 405 Resource Not Allowed : A request was made using an invalid HTTP request
// 		type for the URL requested. For example, you have requested a PUT when a
// 		POST is required. Errors of this type can also triggered by invalid URL
// 		strings.
// 406 Not Acceptable : The requested content type is not supported by the
// 		server.
// 409 Conflict : Request resulted in an update conflict.
// 		{"error":"conflict","reason":"Document update conflict."}
// 412 Precondition Failed : The request headers from the client and the
// 		capabilities of the server do not match.
// 415 Bad Content Type : The content types supported, and the content type of
// 		the information being requested or submitted indicate that the content
// 		type is not supported.
// 416 Requested Range Not Satisfiable : The range specified in the request
// 		header cannot be satisfied by the server.
// 417 Expectation Failed : When sending documents in bulk, the bulk load
// 		operation failed.
// 500 Internal Server Error : The request was invalid, either because the
// 		supplied JSON was invalid, or invalid information was supplied as part
// 		of the request.

// Error represent an error from couchdb
type Error struct {
	StatusCode  int
	CouchdbJSON []byte `json:"-"`
	Name        string `json:"error"`
	Reason      string `json:"reason"`
	Original    error
}

func (e *Error) Error() string {
	if e.CouchdbJSON != nil {
		return fmt.Sprintf("CouchdbError %d : %s", e.StatusCode, e.CouchdbJSON)
	}
	return fmt.Sprintf("CouchdbError %d : %s(%s)", e.StatusCode, e.Name, e.Reason)
}

// JSON returns the hash to ouput in HTTP for a given error
func (e *Error) JSON() map[string]interface{} {
	json := map[string]interface{}{
		"status": string(e.StatusCode),
		"error":  e.Name,
		"reason": e.Reason,
	}
	if e.Original != nil {
		json["original"] = e.Original.Error()
	}
	return json
}

func isNoDatabaseError(err error) bool {
	if err == nil {
		return false
	}
	coucherr, iscoucherr := err.(*Error)
	if !iscoucherr {
		return false
	}
	return coucherr.Reason == "no_db_file" ||
		coucherr.Reason == "Database does not exist."
}

func newRequestError(originalError error) error {
	return &Error{
		StatusCode: http.StatusServiceUnavailable,
		Name:       "no_couch",
		Reason:     "wrong_config",
		Original:   originalError,
	}
}

func newConnectionError(originalError error) error {
	return &Error{
		StatusCode: http.StatusServiceUnavailable,
		Name:       "no_couch",
		Reason:     "cant_connect",
		Original:   originalError,
	}
}

func newIOReadError(originalError error) error {
	return &Error{
		StatusCode: http.StatusServiceUnavailable,
		Name:       "no_couch",
		Reason:     "hangup",
		Original:   originalError,
	}
}

func newCouchdbError(statusCode int, couchdbJSON []byte) error {
	var err = &Error{
		CouchdbJSON: couchdbJSON,
	}
	parseErr := json.Unmarshal(couchdbJSON, err)
	if parseErr != nil {
		err.Name = "wrong_json"
		err.Reason = parseErr.Error()
	}
	err.StatusCode = statusCode
	return err
}
<commit_msg>Change var name to avoid package collision<commit_after>package couchdb

import (
	"encoding/json"
	"fmt"
	"net/http"
)

// This file contains error handling code for couchdb request
// Possible errors in connecting to couchdb
// 503 Service Unavailable when the stack cant connect to couchdb or when
// 		 couchdb response is interrupted mid-stream
// 500 When the viper provided configuration does not allow us to properly
// 		 call http.newRequest, ie. wrong couchdbURL config

// Possible native couchdb errors
// 400 Bad Request : Bad request structure. The error can indicate an error
// 		with the request URL, path or headers. Differences in the supplied MD5
// 		hash and content also trigger this error, as this may indicate message
// 		corruption.
// 401 Unauthorized : The item requested was not available using the supplied
// 		authorization, or authorization was not supplied.
// 		{"error":"unauthorized","reason":"You are not a server admin."}
// 		{"error":"unauthorized","reason":"Name or password is incorrect."}
// 403 Forbidden : The requested item or operation is forbidden.
// 404 Not Found : The requested content could not be found. The content will
// 		include further information, as a JSON object, if available.
// 		**The structure will contain two keys, error and reason.**
//    {"error":"not_found","reason":"deleted"}
//    {"error":"not_found","reason":"missing"}
//    {"error":"not_found","reason":"no_db_file"}
// 405 Resource Not Allowed : A request was made using an invalid HTTP request
// 		type for the URL requested. For example, you have requested a PUT when a
// 		POST is required. Errors of this type can also triggered by invalid URL
// 		strings.
// 406 Not Acceptable : The requested content type is not supported by the
// 		server.
// 409 Conflict : Request resulted in an update conflict.
// 		{"error":"conflict","reason":"Document update conflict."}
// 412 Precondition Failed : The request headers from the client and the
// 		capabilities of the server do not match.
// 415 Bad Content Type : The content types supported, and the content type of
// 		the information being requested or submitted indicate that the content
// 		type is not supported.
// 416 Requested Range Not Satisfiable : The range specified in the request
// 		header cannot be satisfied by the server.
// 417 Expectation Failed : When sending documents in bulk, the bulk load
// 		operation failed.
// 500 Internal Server Error : The request was invalid, either because the
// 		supplied JSON was invalid, or invalid information was supplied as part
// 		of the request.

// Error represent an error from couchdb
type Error struct {
	StatusCode  int
	CouchdbJSON []byte `json:"-"`
	Name        string `json:"error"`
	Reason      string `json:"reason"`
	Original    error
}

func (e *Error) Error() string {
	if e.CouchdbJSON != nil {
		return fmt.Sprintf("CouchdbError %d : %s", e.StatusCode, e.CouchdbJSON)
	}
	return fmt.Sprintf("CouchdbError %d : %s(%s)", e.StatusCode, e.Name, e.Reason)
}

// JSON returns the hash to output in HTTP for a given error
func (e *Error) JSON() map[string]interface{} {
	jsonMap := map[string]interface{}{
		"status": string(e.StatusCode),
		"error":  e.Name,
		"reason": e.Reason,
	}
	if e.Original != nil {
		jsonMap["original"] = e.Original.Error()
	}
	return jsonMap
}

func isNoDatabaseError(err error) bool {
	if err == nil {
		return false
	}
	coucherr, iscoucherr := err.(*Error)
	if !iscoucherr {
		return false
	}
	return coucherr.Reason == "no_db_file" ||
		coucherr.Reason == "Database does not exist."
}

func newRequestError(originalError error) error {
	return &Error{
		StatusCode: http.StatusServiceUnavailable,
		Name:       "no_couch",
		Reason:     "wrong_config",
		Original:   originalError,
	}
}

func newConnectionError(originalError error) error {
	return &Error{
		StatusCode: http.StatusServiceUnavailable,
		Name:       "no_couch",
		Reason:     "cant_connect",
		Original:   originalError,
	}
}

func newIOReadError(originalError error) error {
	return &Error{
		StatusCode: http.StatusServiceUnavailable,
		Name:       "no_couch",
		Reason:     "hangup",
		Original:   originalError,
	}
}

func newCouchdbError(statusCode int, couchdbJSON []byte) error {
	var err = &Error{
		CouchdbJSON: couchdbJSON,
	}
	parseErr := json.Unmarshal(couchdbJSON, err)
	if parseErr != nil {
		err.Name = "wrong_json"
		err.Reason = parseErr.Error()
	}
	err.StatusCode = statusCode
	return err
}
<|endoftext|>