text:
// Copyright 2014 The Bazel Authors. All rights reserved.
//
// 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 com.google.devtools.build.lib.rules.cpp;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.FailAction;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.analysis.Allowlist;
import com.google.devtools.build.lib.analysis.AnalysisUtils;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.DeniedImplicitOutputMarkerProvider;
import com.google.devtools.build.lib.analysis.FileProvider;
import com.google.devtools.build.lib.analysis.FilesToRunProvider;
import com.google.devtools.build.lib.analysis.MakeVariableSupplier.MapBackedMakeVariableSupplier;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetFactory;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.RuleErrorConsumer;
import com.google.devtools.build.lib.analysis.Runfiles;
import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.test.InstrumentedFilesInfo;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction;
import com.google.devtools.build.lib.packages.RawAttributeMapper;
import com.google.devtools.build.lib.packages.TargetUtils;
import com.google.devtools.build.lib.packages.Type;
import com.google.devtools.build.lib.rules.cpp.CcCommon.CcFlagsSupplier;
import com.google.devtools.build.lib.rules.cpp.CcCompilationHelper.CompilationInfo;
import com.google.devtools.build.lib.rules.cpp.CcToolchainFeatures.FeatureConfiguration;
import com.google.devtools.build.lib.rules.cpp.Link.LinkTargetType;
import com.google.devtools.build.lib.server.FailureDetails.FailAction.Code;
import com.google.devtools.build.lib.util.FileTypeSet;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import net.starlark.java.eval.EvalException;

/**
 * A ConfiguredTarget for cc_library rules.
 */
public abstract class CcLibrary implements RuleConfiguredTargetFactory {

  /** A string constant for the name of archive library(.a, .lo) output group. */
  public static final String ARCHIVE_LIBRARY_OUTPUT_GROUP_NAME = "archive";

  /** A string constant for the name of dynamic library output group. */
  public static final String DYNAMIC_LIBRARY_OUTPUT_GROUP_NAME = "dynamic_library";

  /** A string constant for the name of Windows def file output group. */
  public static final String DEF_FILE_OUTPUT_GROUP_NAME = "def_file";

  public static final String IMPLICIT_OUTPUTS_ALLOWLIST = "allowed_cc_lib_implicit_outputs";

  private final CppSemantics semantics;

  protected CcLibrary(CppSemantics semantics) {
    this.semantics = semantics;
  }

  // These file extensions don't generate object files.
  private static final FileTypeSet NO_OBJECT_GENERATING_FILETYPES = FileTypeSet.of(
      CppFileTypes.CPP_HEADER, CppFileTypes.ARCHIVE, CppFileTypes.PIC_ARCHIVE,
      CppFileTypes.ALWAYS_LINK_LIBRARY, CppFileTypes.ALWAYS_LINK_PIC_LIBRARY,
      CppFileTypes.SHARED_LIBRARY, CppFileTypes.VERSIONED_SHARED_LIBRARY);

  @Override
  public ConfiguredTarget create(RuleContext context)
      throws InterruptedException, RuleErrorException, ActionConflictException {
    RuleConfiguredTargetBuilder builder = new RuleConfiguredTargetBuilder(context);
    boolean linkStatic = context.attributes().get("linkstatic", Type.BOOLEAN);
    init(
        semantics,
        context,
        builder,
        /* additionalCopts= */ ImmutableList.of(),
        /* soFilename= */ null,
        context.attributes().get("alwayslink", Type.BOOLEAN),
        /* neverLink= */ false,
        linkStatic,
        /* addDynamicRuntimeInputArtifactsToRunfiles= */ false);
    return builder.build();
  }

  public static void init(
      CppSemantics semantics,
      RuleContext ruleContext,
      RuleConfiguredTargetBuilder targetBuilder,
      ImmutableList<String> additionalCopts,
      PathFragment soFilename,
      boolean alwaysLink,
      boolean neverLink,
      boolean linkStatic,
      boolean addDynamicRuntimeInputArtifactsToRunfiles)
      throws RuleErrorException, InterruptedException {
    semantics.validateDeps(ruleContext);
    if (ruleContext.hasErrors()) {
      addEmptyRequiredProviders(targetBuilder);
      return;
    }

    final CcCommon common = new CcCommon(ruleContext);
    common.reportInvalidOptions(ruleContext);

    CcToolchainProvider ccToolchain = common.getToolchain();
    CppConfiguration cppConfiguration = ruleContext.getFragment(CppConfiguration.class);

    ImmutableMap.Builder<String, String> toolchainMakeVariables = ImmutableMap.builder();
    ccToolchain.addGlobalMakeVariables(toolchainMakeVariables);
    ruleContext.initConfigurationMakeVariableContext(
        new MapBackedMakeVariableSupplier(toolchainMakeVariables.build()),
        new CcFlagsSupplier(ruleContext));

    FdoContext fdoContext = common.getFdoContext();
    FeatureConfiguration featureConfiguration =
        CcCommon.configureFeaturesOrReportRuleError(ruleContext, ccToolchain, semantics);
    PrecompiledFiles precompiledFiles = new PrecompiledFiles(ruleContext);

    semantics.validateAttributes(ruleContext);
    if (ruleContext.hasErrors()) {
      addEmptyRequiredProviders(targetBuilder);
      return;
    }

    ImmutableList<TransitiveInfoCollection> deps =
        ImmutableList.copyOf(ruleContext.getPrerequisites("deps"));
    if (ruleContext.hasErrors()) {
      addEmptyRequiredProviders(targetBuilder);
      return;
    }
    Iterable<CcInfo> ccInfosFromDeps = AnalysisUtils.getProviders(deps, CcInfo.PROVIDER);
    CcCompilationHelper compilationHelper =
        new CcCompilationHelper(
                ruleContext,
                ruleContext,
                ruleContext.getLabel(),
                CppHelper.getGrepIncludes(ruleContext),
                semantics,
                featureConfiguration,
                ccToolchain,
                fdoContext,
                TargetUtils.getExecutionInfo(
                    ruleContext.getRule(), ruleContext.isAllowTagsPropagation()),
                /* shouldProcessHeaders= */ true)
            .fromCommon(common, additionalCopts)
            .addSources(common.getSources())
            .addPrivateHeaders(common.getPrivateHeaders())
            .addPublicHeaders(common.getHeaders())
            .setCodeCoverageEnabled(CcCompilationHelper.isCodeCoverageEnabled(ruleContext))
            .addCcCompilationContexts(
                Streams.stream(ccInfosFromDeps)
                    .map(CcInfo::getCcCompilationContext)
                    .collect(ImmutableList.toImmutableList()))
            .addCcCompilationContexts(
                ImmutableList.of(CcCompilationHelper.getStlCcCompilationContext(ruleContext)))
            .setHeadersCheckingMode(semantics.determineHeadersCheckingMode(ruleContext));

    CcLinkingHelper linkingHelper =
        new CcLinkingHelper(
                ruleContext,
                ruleContext.getLabel(),
                ruleContext,
                ruleContext,
                semantics,
                featureConfiguration,
                ccToolchain,
                fdoContext,
                ruleContext.getConfiguration(),
                ruleContext.getFragment(CppConfiguration.class),
                ruleContext.getSymbolGenerator(),
                TargetUtils.getExecutionInfo(
                    ruleContext.getRule(), ruleContext.isAllowTagsPropagation()))
            .fromCommon(ruleContext, common)
            .setGrepIncludes(CppHelper.getGrepIncludes(ruleContext))
            .setTestOrTestOnlyTarget(ruleContext.isTestOnlyTarget())
            .addLinkopts(common.getLinkopts())
            .emitInterfaceSharedLibraries(true)
            .setAlwayslink(alwaysLink)
            .setNeverLink(neverLink)
            .addLinkstamps(ruleContext.getPrerequisites("linkstamp"));

    Artifact soImplArtifact = null;
    boolean supportsDynamicLinker = ccToolchain.supportsDynamicLinker(featureConfiguration);
    // TODO(djasper): This is hacky. We should actually try to figure out whether we generate
    // ccOutputs.
    boolean createDynamicLibrary =
        !linkStatic
            && supportsDynamicLinker
            && (appearsToHaveObjectFiles(ruleContext.attributes())
                || featureConfiguration.isEnabled(CppRuleClasses.HEADER_MODULE_CODEGEN));
    if (soFilename != null) {
      if (!soFilename.getPathString().endsWith(".so")) {
        ruleContext.attributeError("outs", "file name must end in '.so'");
      }
      if (createDynamicLibrary) {
        soImplArtifact = ruleContext.getBinArtifact(soFilename);
      }
    }

    if (ruleContext.getRule().isAttrDefined("textual_hdrs", BuildType.LABEL_LIST)) {
      compilationHelper.addPublicTextualHeaders(
          ruleContext.getPrerequisiteArtifacts("textual_hdrs").list());
    }
    if (ruleContext.getRule().isAttrDefined("include_prefix", Type.STRING)
        && ruleContext.attributes().isAttributeValueExplicitlySpecified("include_prefix")) {
      compilationHelper.setIncludePrefix(
          ruleContext.attributes().get("include_prefix", Type.STRING));
    }
    if (ruleContext.getRule().isAttrDefined("strip_include_prefix", Type.STRING)
        && ruleContext.attributes().isAttributeValueExplicitlySpecified("strip_include_prefix")) {
      compilationHelper.setStripIncludePrefix(
          ruleContext.attributes().get("strip_include_prefix", Type.STRING));
    }

    if (common.getLinkopts().contains("-static")) {
      ruleContext.attributeWarning("linkopts", "Using '-static' here won't work. "
                                   + "Did you mean to use 'linkstatic=1' instead?");
    }

    linkingHelper.setShouldCreateDynamicLibrary(createDynamicLibrary);
    linkingHelper.setLinkerOutputArtifact(soImplArtifact);

    // If the reason we're not creating a dynamic library is that the toolchain
    // doesn't support it, then register an action which complains when triggered,
    // which only happens when some rule explicitly depends on the dynamic library.
    if (!createDynamicLibrary && !supportsDynamicLinker) {
      ImmutableList.Builder<Artifact> dynamicLibraries = ImmutableList.builder();
      dynamicLibraries.add(
          CppHelper.getLinkedArtifact(
              ruleContext,
              ccToolchain,
              ruleContext.getConfiguration(),
              LinkTargetType.NODEPS_DYNAMIC_LIBRARY,
              CppHelper.getDLLHashSuffix(ruleContext, featureConfiguration)));
      if (CppHelper.useInterfaceSharedLibraries(
          cppConfiguration, ccToolchain, featureConfiguration)) {
        dynamicLibraries.add(
            CppHelper.getLinkedArtifact(
                ruleContext,
                ccToolchain,
                ruleContext.getConfiguration(),
                LinkTargetType.INTERFACE_DYNAMIC_LIBRARY));
      }
      ruleContext.registerAction(
          new FailAction(
              ruleContext.getActionOwner(),
              dynamicLibraries.build(),
              "Toolchain does not support dynamic linking",
              Code.DYNAMIC_LINKING_NOT_SUPPORTED));
    } else if (!createDynamicLibrary
        && ruleContext.attributes().isConfigurable("srcs")) {
      // If "srcs" is configurable, the .so output is always declared because the logic that
      // determines implicit outs doesn't know which value of "srcs" will ultimately get chosen.
      // Here, where we *do* have the correct value, it may not contain any source files to
      // generate an .so with. If that's the case, register a fake generating action to prevent
      // a "no generating action for this artifact" error.
      ImmutableList.Builder<Artifact> dynamicLibraries = ImmutableList.builder();
      dynamicLibraries.add(
          CppHelper.getLinkedArtifact(
              ruleContext,
              ccToolchain,
              ruleContext.getConfiguration(),
              LinkTargetType.NODEPS_DYNAMIC_LIBRARY,
              CppHelper.getDLLHashSuffix(ruleContext, featureConfiguration)));
      if (CppHelper.useInterfaceSharedLibraries(
          cppConfiguration, ccToolchain, featureConfiguration)) {
        dynamicLibraries.add(
            CppHelper.getLinkedArtifact(
                ruleContext,
                ccToolchain,
                ruleContext.getConfiguration(),
                LinkTargetType.INTERFACE_DYNAMIC_LIBRARY));
      }
      ruleContext.registerAction(
          new FailAction(
              ruleContext.getActionOwner(),
              dynamicLibraries.build(),
              "configurable \"srcs\" triggers an implicit .so output even though there are no"
                  + " sources to compile in this configuration",
              Code.SOURCE_FILES_MISSING));
    }

    CompilationInfo compilationInfo = compilationHelper.compile(ruleContext);
    CcCompilationOutputs precompiledFilesObjects =
        CcCompilationOutputs.builder()
            .addObjectFiles(precompiledFiles.getObjectFiles(/* usePic= */ true))
            .addPicObjectFiles(precompiledFiles.getObjectFiles(/* usePic= */ true))
            .build();
    CcCompilationOutputs ccCompilationOutputs =
        CcCompilationOutputs.builder()
            .merge(precompiledFilesObjects)
            .merge(compilationInfo.getCcCompilationOutputs())
            .build();

    // Generate .a and .so outputs even without object files to fulfill the rule class
    // contract wrt. implicit output files, if the contract says so. Behavior here differs
    // between Bazel and Blaze.
    CcLinkingOutputs ccLinkingOutputs = CcLinkingOutputs.EMPTY;
    if (ruleContext.getRule().getImplicitOutputsFunction() != ImplicitOutputsFunction.NONE
        || !ccCompilationOutputs.isEmpty()) {
      if (featureConfiguration.isEnabled(CppRuleClasses.TARGETS_WINDOWS)) {
        String dllNameSuffix = CppHelper.getDLLHashSuffix(ruleContext, featureConfiguration);
        linkingHelper.setLinkedDLLNameSuffix(dllNameSuffix);
        Artifact generatedDefFile = null;

        Artifact defParser = common.getDefParser();
        if (defParser != null) {
          try {
            generatedDefFile =
                CppHelper.createDefFileActions(
                    ruleContext,
                    defParser,
                    ccCompilationOutputs.getObjectFiles(false),
                    ccToolchain
                        .getFeatures()
                        .getArtifactNameForCategory(
                            ArtifactCategory.DYNAMIC_LIBRARY,
                            ruleContext.getLabel().getName() + dllNameSuffix));
            targetBuilder.addOutputGroup(DEF_FILE_OUTPUT_GROUP_NAME, generatedDefFile);
          } catch (EvalException e) {
            throw ruleContext.throwWithRuleError(e);
          }
        }
        linkingHelper.setDefFile(
            CppHelper.getWindowsDefFileForLinking(
                ruleContext, common.getWinDefFile(), generatedDefFile, featureConfiguration));
      }
      ccLinkingOutputs = linkingHelper.link(ccCompilationOutputs);
    }

    ImmutableSortedMap.Builder<String, NestedSet<Artifact>> outputGroups =
        ImmutableSortedMap.naturalOrder();
    if (!ccLinkingOutputs.isEmpty()) {
      outputGroups.putAll(
          addLinkerOutputArtifacts(
              ruleContext,
              ccToolchain,
              cppConfiguration,
              ruleContext.getConfiguration(),
              ccCompilationOutputs,
              featureConfiguration));
    }
    List<LibraryToLink> precompiledLibraries =
        convertPrecompiledLibrariesToLibraryToLink(
            ruleContext,
            common,
            ruleContext.getFragment(CppConfiguration.class).forcePic(),
            precompiledFiles);

    if (!ccCompilationOutputs.isEmpty()) {
      checkIfLinkOutputsCollidingWithPrecompiledFiles(
          ruleContext, ccLinkingOutputs, precompiledLibraries);
    }

    ImmutableList<LibraryToLink> libraryToLinks =
        createLibrariesToLinkList(
            ccLinkingOutputs.getLibraryToLink(),
            precompiledLibraries,
            ccCompilationOutputs.isEmpty());

    CcLinkingContext ccLinkingContext =
        linkingHelper.buildCcLinkingContextFromLibrariesToLink(
            neverLink ? ImmutableList.of() : libraryToLinks,
            compilationInfo.getCcCompilationContext());
    CcNativeLibraryInfo ccNativeLibraryInfo =
        CppHelper.collectNativeCcLibraries(ruleContext.getPrerequisites("deps"), libraryToLinks);

    /*
     * We always generate a static library, even if there aren't any source files.
     * This keeps things simpler by avoiding special cases when making use of the library.
     * For example, this is needed to ensure that building a library with "bazel build"
     * will also build all of the library's "deps".
     * However, we only generate a dynamic library if there are source files.
     */
    // For now, we don't add the precompiled libraries to the files to build.

    NestedSetBuilder<Artifact> filesBuilder = NestedSetBuilder.stableOrder();
    if (!ccLinkingOutputs.isEmpty()) {
      LibraryToLink artifactsToBuild = ccLinkingOutputs.getLibraryToLink();
      if (artifactsToBuild.getStaticLibrary() != null) {
        filesBuilder.add(artifactsToBuild.getStaticLibrary());
      }
      if (artifactsToBuild.getPicStaticLibrary() != null) {
        filesBuilder.add(artifactsToBuild.getPicStaticLibrary());
      }
      if (!featureConfiguration.isEnabled(CppRuleClasses.TARGETS_WINDOWS)) {
        if (artifactsToBuild.getResolvedSymlinkDynamicLibrary() != null) {
          filesBuilder.add(artifactsToBuild.getResolvedSymlinkDynamicLibrary());
        } else if (artifactsToBuild.getDynamicLibrary() != null) {
          filesBuilder.add(artifactsToBuild.getDynamicLibrary());
        }
        if (artifactsToBuild.getResolvedSymlinkInterfaceLibrary() != null) {
          filesBuilder.add(artifactsToBuild.getResolvedSymlinkInterfaceLibrary());
        } else if (artifactsToBuild.getInterfaceLibrary() != null) {
          filesBuilder.add(artifactsToBuild.getInterfaceLibrary());
        }
      }
    }

    if (!featureConfiguration.isEnabled(CppRuleClasses.HEADER_MODULE_CODEGEN)) {
      warnAboutEmptyLibraries(ruleContext, ccCompilationOutputs, linkStatic);
    }
    NestedSet<Artifact> filesToBuild = filesBuilder.build();

    List<Artifact> instrumentedObjectFiles = new ArrayList<>();
    instrumentedObjectFiles.addAll(compilationInfo.getCcCompilationOutputs().getObjectFiles(false));
    instrumentedObjectFiles.addAll(compilationInfo.getCcCompilationOutputs().getObjectFiles(true));
    InstrumentedFilesInfo instrumentedFilesProvider =
        common.getInstrumentedFilesProvider(
            instrumentedObjectFiles,
            /* withBaselineCoverage= */ true,
            /* virtualToOriginalHeaders= */ NestedSetBuilder.create(Order.STABLE_ORDER),
            /* additionalMetadata= */ null);
    CppHelper.maybeAddStaticLinkMarkerProvider(targetBuilder, ruleContext);

    Runfiles.Builder builder = new Runfiles.Builder(ruleContext.getWorkspaceName());
    builder.addDataDeps(ruleContext);
    builder.add(ruleContext, RunfilesProvider.DEFAULT_RUNFILES);
    if (addDynamicRuntimeInputArtifactsToRunfiles) {
      try {
        builder.addTransitiveArtifacts(
            ccToolchain.getDynamicRuntimeLinkInputs(featureConfiguration));
      } catch (EvalException e) {
        throw ruleContext.throwWithRuleError(e);
      }
    }
    Runfiles runfiles = builder.build();
    Runfiles.Builder defaultRunfiles =
        new Runfiles.Builder(ruleContext.getWorkspaceName())
            .merge(runfiles)
            .addArtifacts(LibraryToLink.getDynamicLibrariesForRuntime(!neverLink, libraryToLinks));

    Runfiles.Builder dataRunfiles =
        new Runfiles.Builder(ruleContext.getWorkspaceName())
            .merge(runfiles)
            .addArtifacts(
                LibraryToLink.getDynamicLibrariesForRuntime(
                    /* linkingStatically= */ false, libraryToLinks));

    Map<String, NestedSet<Artifact>> currentOutputGroups =
        CcCompilationHelper.buildOutputGroupsForEmittingCompileProviders(
            compilationInfo.getCcCompilationOutputs(),
            compilationInfo.getCcCompilationContext(),
            ruleContext.getFragment(CppConfiguration.class),
            ccToolchain,
            featureConfiguration,
            ruleContext,
            /* generateHeaderTokensGroup= */ true,
            /* addSelfHeaderTokens= */ true,
            /* generateHiddenTopLevelGroup= */ true);
    CcStarlarkApiProvider.maybeAdd(ruleContext, targetBuilder);
    targetBuilder
        .setFilesToBuild(filesToBuild)
        .addNativeDeclaredProvider(
            CcInfo.builder()
                .setCcCompilationContext(compilationInfo.getCcCompilationContext())
                .setCcLinkingContext(ccLinkingContext)
                .setCcDebugInfoContext(
                    CppHelper.mergeCcDebugInfoContexts(
                        compilationInfo.getCcCompilationOutputs(), ccInfosFromDeps))
                .setCcNativeLibraryInfo(ccNativeLibraryInfo)
                .build())
        .addOutputGroups(
            CcCommon.mergeOutputGroups(ImmutableList.of(currentOutputGroups, outputGroups.build())))
        .addNativeDeclaredProvider(instrumentedFilesProvider)
        .addProvider(RunfilesProvider.withData(defaultRunfiles.build(), dataRunfiles.build()));

    maybeAddDeniedImplicitOutputsProvider(targetBuilder, ruleContext);
  }

  private static void maybeAddDeniedImplicitOutputsProvider(
      RuleConfiguredTargetBuilder targetBuilder, RuleContext ruleContext) {
    if (ruleContext.getRule().getImplicitOutputsFunction() != ImplicitOutputsFunction.NONE
        && !Allowlist.isAvailable(ruleContext, IMPLICIT_OUTPUTS_ALLOWLIST)) {
      targetBuilder.addNativeDeclaredProvider(
          new DeniedImplicitOutputMarkerProvider(
              String.format(
                  "Using implicit outputs from cc_library (%s) is forbidden. Use the rule"
                      + " cc_implicit_output as an alternative.",
                  ruleContext.getLabel())));
    }
  }

  private static void warnAboutEmptyLibraries(RuleContext ruleContext,
      CcCompilationOutputs ccCompilationOutputs,
      boolean linkstaticAttribute) {
    if (ccCompilationOutputs.getObjectFiles(false).isEmpty()
        && ccCompilationOutputs.getObjectFiles(true).isEmpty()) {
      if (!linkstaticAttribute && appearsToHaveObjectFiles(ruleContext.attributes())) {
        ruleContext.attributeWarning("linkstatic",
            "setting 'linkstatic=1' is recommended if there are no object files");
      }
    } else {
      if (!linkstaticAttribute && !appearsToHaveObjectFiles(ruleContext.attributes())) {
        Artifact element = Iterables.getFirst(
            ccCompilationOutputs.getObjectFiles(false),
            ccCompilationOutputs.getObjectFiles(true).get(0));
        ruleContext.attributeWarning("srcs",
             "this library appears at first glance to have no object files, "
             + "but on closer inspection it does have something to link, e.g. "
             + element.prettyPrint() + ". "
             + "(You may have used some very confusing rule names in srcs? "
             + "Or the library consists entirely of a linker script?) "
             + "Bazel assumed linkstatic=1, but this may be inappropriate. "
             + "You may need to add an explicit '.cc' file to 'srcs'. "
             + "Alternatively, add 'linkstatic=1' to suppress this warning");
      }
    }
  }

  /**
   * Returns true if the rule (which must be a cc_library rule) appears to have object files.
   * This only looks at the rule itself, not at any other rules (from this package or other
   * packages) that it might reference.
   *
   *
In some cases, this may return "true" even though the rule actually has no object files.
   * For example, it will return true for a rule such as
   * cc_library(name = 'foo', srcs = [':bar']) because we can't tell what ':bar' is;
   * it might be a genrule that generates a source file, or it might be a genrule that generates a
   * header file. Likewise,
   * cc_library(name = 'foo', srcs = select({':a': ['foo.cc'], ':b': []})) returns
   * "true" even though the sources *may* be empty. This reflects the fact that there's no way
   * to tell which value "srcs" will take without knowing the rule's configuration.
   *
   *
In other cases, this may return "false" even though the rule actually does have object
   * files. For example, it will return false for a rule such as
   * cc_library(name = 'foo', srcs = ['bar.h']) but as in the other example above,
   * we can't tell whether 'bar.h' is a file name or a rule name, and 'bar.h' could in fact be the
   * name of a genrule that generates a source file.
   */
  public static boolean appearsToHaveObjectFiles(AttributeMap rule) {
    if ((rule instanceof RawAttributeMapper) && rule.isConfigurable("srcs")) {
      // Since this method gets called by loading phase logic (e.g. the cc_library implicit outputs
      // function), the attribute mapper may not be able to resolve configurable attributes. When
      // that's the case, there's no way to know which value a configurable "srcs" will take, so
      // we conservatively assume object files are possible.
      return true;
    }

    List srcs = rule.get("srcs", BuildType.LABEL_LIST);
    if (srcs != null) {
      for (Label srcfile : srcs) {
        /*
         * We cheat a little bit here by looking at the file extension
         * of the Label treated as file name.  In general that might
         * not necessarily work, because of the possibility that the
         * user might give a rule a funky name ending in one of these
         * extensions, e.g.
         *    genrule(name = 'foo.h', outs = ['foo.cc'], ...) // Funky rule name!
         *    cc_library(name = 'bar', srcs = ['foo.h']) // This DOES have object files.
         */
        if (!NO_OBJECT_GENERATING_FILETYPES.matches(srcfile.getName())) {
          return true;
        }
      }
    }
    return false;
  }

  /**
   * Adds linker output artifacts to the given map, to be registered on the configured target as
   * output groups.
   */
  private static Map<String, NestedSet<Artifact>> addLinkerOutputArtifacts(
      RuleContext ruleContext,
      CcToolchainProvider ccToolchain,
      CppConfiguration cppConfiguration,
      BuildConfiguration configuration,
      CcCompilationOutputs ccCompilationOutputs,
      FeatureConfiguration featureConfiguration)
      throws RuleErrorException {

    NestedSetBuilder<Artifact> archiveFile = new NestedSetBuilder<>(Order.STABLE_ORDER);
    NestedSetBuilder<Artifact> dynamicLibrary = new NestedSetBuilder<>(Order.STABLE_ORDER);

    ImmutableSortedMap.Builder<String, NestedSet<Artifact>> outputGroups =
        ImmutableSortedMap.naturalOrder();
    if (!ruleContext.attributes().has("alwayslink", Type.BOOLEAN)
        || !ruleContext.attributes().has("linkstatic", Type.BOOLEAN)) {
      return outputGroups.build();
    }

    if (ruleContext.attributes().get("alwayslink", Type.BOOLEAN)) {
      archiveFile.add(
          CppHelper.getLinkedArtifact(
              ruleContext,
              ccToolchain,
              configuration,
              Link.LinkTargetType.ALWAYS_LINK_STATIC_LIBRARY,
              /* linkedArtifactNameSuffix= */ ""));
    } else {
      archiveFile.add(
          CppHelper.getLinkedArtifact(
              ruleContext,
              ccToolchain,
              configuration,
              Link.LinkTargetType.STATIC_LIBRARY,
              /* linkedArtifactNameSuffix= */ ""));
    }

    if (!ruleContext.attributes().get("linkstatic", Type.BOOLEAN)
        && !ccCompilationOutputs.isEmpty()) {
      dynamicLibrary.add(
          CppHelper.getLinkedArtifact(
              ruleContext,
              ccToolchain,
              configuration,
              Link.LinkTargetType.NODEPS_DYNAMIC_LIBRARY,
              CppHelper.getDLLHashSuffix(ruleContext, featureConfiguration)));

      if (CppHelper.useInterfaceSharedLibraries(
          cppConfiguration, ccToolchain, featureConfiguration)) {
        dynamicLibrary.add(
            CppHelper.getLinkedArtifact(
                ruleContext,
                ccToolchain,
                configuration,
                LinkTargetType.INTERFACE_DYNAMIC_LIBRARY,
                /* linkedArtifactNameSuffix= */ ""));
      }
    }

    outputGroups.put(ARCHIVE_LIBRARY_OUTPUT_GROUP_NAME, archiveFile.build());
    outputGroups.put(DYNAMIC_LIBRARY_OUTPUT_GROUP_NAME, dynamicLibrary.build());
    return outputGroups.build();
  }

  private static ImmutableList<LibraryToLink> createLibrariesToLinkList(
      @Nullable LibraryToLink outputLibrary,
      List<LibraryToLink> precompiledLibraries,
      boolean ccCompilationOutputsIsEmpty) {
    ImmutableList.Builder<LibraryToLink> librariesToLink = ImmutableList.builder();
    librariesToLink.addAll(precompiledLibraries);

    // For cc_library if it contains precompiled libraries we link them. If it contains normal
    // sources we link them as well, if it doesn't contain normal sources, then we don't do
    // anything else if there were  precompiled libraries. However, if there are no precompiled
    // libraries and there are no normal sources, then we use the implicitly created link output
    // files if they exist.
    if (!ccCompilationOutputsIsEmpty
        || (precompiledLibraries.isEmpty()
            && isContentsOfCcLinkingOutputsImplicitlyCreated(
                ccCompilationOutputsIsEmpty, outputLibrary == null))) {
      if (outputLibrary != null) {
        librariesToLink.add(outputLibrary);
      }
    }

    return librariesToLink.build();
  }

  private static boolean isContentsOfCcLinkingOutputsImplicitlyCreated(
      boolean ccCompilationOutputsIsEmpty, boolean ccLinkingOutputsIsEmpty) {
    return ccCompilationOutputsIsEmpty && !ccLinkingOutputsIsEmpty;
  }

  private static ImmutableMap<String, Artifact> buildMapIdentifierToArtifact(
      RuleErrorConsumer ruleErrorConsumer, Iterable<Artifact> artifacts) {
    Map<String, Artifact> libraries = new LinkedHashMap<>();
    for (Artifact artifact : artifacts) {
      String identifier = CcLinkingOutputs.libraryIdentifierOf(artifact);
      if (libraries.containsKey(identifier)) {
        ruleErrorConsumer.attributeError(
            "srcs",
            String.format(
                "Trying to link twice a library with the same identifier '%s', files: %s and %s",
                identifier, artifact.toDetailString(), libraries.get(identifier).toDetailString()));
      }
      libraries.put(identifier, artifact);
    }
    return ImmutableMap.copyOf(libraries);
  }

  /*
   * Add the libraries from srcs, if any. For static/mostly static
   * linking we setup the dynamic libraries if there are no static libraries
   * to choose from. Path to the libraries will be mangled to avoid using
   * absolute path names on the -rpath, but library filenames will be
   * preserved (since some libraries might have SONAME tag) - symlink will
   * be created to the parent directory instead.
   *
   * For compatibility with existing BUILD files, any ".a" or ".lo" files listed in
   * srcs are assumed to be position-independent code, or at least suitable for
   * inclusion in shared libraries, unless they end with ".nopic.a" or ".nopic.lo".
   *
   * Note that some target platforms do not require shared library code to be PIC.
   */
  private static List<LibraryToLink> convertPrecompiledLibrariesToLibraryToLink(
      RuleErrorConsumer ruleErrorConsumer,
      CcCommon common,
      boolean forcePic,
      PrecompiledFiles precompiledFiles) {
    ImmutableList.Builder<LibraryToLink> librariesToLink = ImmutableList.builder();

    Map<String, Artifact> staticLibraries =
        buildMapIdentifierToArtifact(ruleErrorConsumer, precompiledFiles.getStaticLibraries());
    Map<String, Artifact> picStaticLibraries =
        buildMapIdentifierToArtifact(ruleErrorConsumer, precompiledFiles.getPicStaticLibraries());
    Map<String, Artifact> alwayslinkStaticLibraries =
        buildMapIdentifierToArtifact(
            ruleErrorConsumer, precompiledFiles.getAlwayslinkStaticLibraries());
    Map<String, Artifact> alwayslinkPicStaticLibraries =
        buildMapIdentifierToArtifact(
            ruleErrorConsumer, precompiledFiles.getPicAlwayslinkLibraries());
    Map<String, Artifact> dynamicLibraries =
        buildMapIdentifierToArtifact(ruleErrorConsumer, precompiledFiles.getSharedLibraries());

    Set<String> identifiersUsed = new HashSet<>();
    for (Map.Entry<String, Artifact> staticLibraryEntry :
        Iterables.concat(staticLibraries.entrySet(), alwayslinkStaticLibraries.entrySet())) {
      LibraryToLink.Builder libraryToLinkBuilder = LibraryToLink.builder();
      String identifier = staticLibraryEntry.getKey();
      libraryToLinkBuilder.setLibraryIdentifier(identifier);
      boolean hasPic = picStaticLibraries.containsKey(identifier);
      boolean hasAlwaysPic = alwayslinkPicStaticLibraries.containsKey(identifier);
      if (hasPic || hasAlwaysPic) {
        Artifact picStaticLibrary = null;
        if (hasPic) {
          picStaticLibrary = picStaticLibraries.get(identifier);
        } else {
          picStaticLibrary = alwayslinkPicStaticLibraries.get(identifier);
        }
        libraryToLinkBuilder.setPicStaticLibrary(picStaticLibrary);
      }
      if (!forcePic || !(hasPic || hasAlwaysPic)) {
        libraryToLinkBuilder.setStaticLibrary(staticLibraryEntry.getValue());
      }
      if (dynamicLibraries.containsKey(identifier)) {
        Artifact library = dynamicLibraries.get(identifier);
        Artifact symlink = common.getDynamicLibrarySymlink(library, true);
        libraryToLinkBuilder.setDynamicLibrary(symlink);
        libraryToLinkBuilder.setResolvedSymlinkDynamicLibrary(library);
      }
      libraryToLinkBuilder.setAlwayslink(alwayslinkStaticLibraries.containsKey(identifier));
      identifiersUsed.add(identifier);
      librariesToLink.add(libraryToLinkBuilder.build());
    }

    for (Map.Entry<String, Artifact> picStaticLibraryEntry :
        Iterables.concat(picStaticLibraries.entrySet(), alwayslinkPicStaticLibraries.entrySet())) {
      String identifier = picStaticLibraryEntry.getKey();
      if (identifiersUsed.contains(identifier)) {
        continue;
      }
      LibraryToLink.Builder libraryToLinkBuilder = LibraryToLink.builder();
      libraryToLinkBuilder.setLibraryIdentifier(identifier);
      libraryToLinkBuilder.setPicStaticLibrary(picStaticLibraryEntry.getValue());
      if (dynamicLibraries.containsKey(identifier)) {
        Artifact library = dynamicLibraries.get(identifier);
        Artifact symlink = common.getDynamicLibrarySymlink(library, true);
        libraryToLinkBuilder.setDynamicLibrary(symlink);
        libraryToLinkBuilder.setResolvedSymlinkDynamicLibrary(library);
      }
      libraryToLinkBuilder.setAlwayslink(alwayslinkPicStaticLibraries.containsKey(identifier));
      identifiersUsed.add(identifier);
      librariesToLink.add(libraryToLinkBuilder.build());
    }

    for (Map.Entry<String, Artifact> dynamicLibraryEntry : dynamicLibraries.entrySet()) {
      String identifier = dynamicLibraryEntry.getKey();
      if (identifiersUsed.contains(identifier)) {
        continue;
      }
      LibraryToLink.Builder libraryToLinkBuilder = LibraryToLink.builder();
      libraryToLinkBuilder.setLibraryIdentifier(identifier);
      Artifact library = dynamicLibraryEntry.getValue();
      Artifact symlink = common.getDynamicLibrarySymlink(library, true);
      libraryToLinkBuilder.setDynamicLibrary(symlink);
      libraryToLinkBuilder.setResolvedSymlinkDynamicLibrary(library);
      librariesToLink.add(libraryToLinkBuilder.build());
    }
    return librariesToLink.build();
  }

  private static void checkIfLinkOutputsCollidingWithPrecompiledFiles(
      RuleContext ruleContext,
      CcLinkingOutputs ccLinkingOutputs,
      List<LibraryToLink> precompiledLibraries) {
    String identifier = ccLinkingOutputs.getLibraryToLink().getLibraryIdentifier();
    for (LibraryToLink precompiledLibrary : precompiledLibraries) {
      if (identifier.equals(precompiledLibrary.getLibraryIdentifier())) {
        ruleContext.ruleError(
            "Can't put library with identifier '"
                + precompiledLibrary.getLibraryIdentifier()
                + "' into the srcs of a "
                + ruleContext.getRuleClassNameForLogging()
                + " with the same name ("
                + ruleContext.getRule().getName()
                + ") which also contains other code or objects to link");
      }
    }
  }

  private static void addEmptyRequiredProviders(RuleConfiguredTargetBuilder builder) {
    builder.addProvider(RunfilesProvider.EMPTY);
    builder.addProvider(FileProvider.EMPTY);
    builder.addProvider(FilesToRunProvider.EMPTY);
  }
}


text:
ACCEPTED

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
Lichenologist 32(1): 23 (2000)

#### Original name
null

### Remarks
null

redpajama_set_name: RedPajamaGithub


text:
package archive

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

	"github.com/cloudcredo/cloudrocker/Godeps/_workspace/src/github.com/fsouza/go-dockerclient/external/github.com/Sirupsen/logrus"
	"github.com/cloudcredo/cloudrocker/Godeps/_workspace/src/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/idtools"
	"github.com/cloudcredo/cloudrocker/Godeps/_workspace/src/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/pools"
	"github.com/cloudcredo/cloudrocker/Godeps/_workspace/src/github.com/fsouza/go-dockerclient/external/github.com/docker/docker/pkg/system"
)

// UnpackLayer unpack `layer` to a `dest`. The stream `layer` can be
// compressed or uncompressed.
// Returns the size in bytes of the contents of the layer.
func UnpackLayer(dest string, layer Reader, options *TarOptions) (size int64, err error) {
	tr := tar.NewReader(layer)
	trBuf := pools.BufioReader32KPool.Get(tr)
	defer pools.BufioReader32KPool.Put(trBuf)

	var dirs []*tar.Header

	if options == nil {
		options = &TarOptions{}
	}
	if options.ExcludePatterns == nil {
		options.ExcludePatterns = []string{}
	}
	remappedRootUID, remappedRootGID, err := idtools.GetRootUIDGID(options.UIDMaps, options.GIDMaps)
	if err != nil {
		return 0, err
	}

	aufsTempdir := ""
	aufsHardlinks := make(map[string]*tar.Header)

	if options == nil {
		options = &TarOptions{}
	}
	// Iterate through the files in the archive.
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			// end of tar archive
			break
		}
		if err != nil {
			return 0, err
		}

		size += hdr.Size

		// Normalize name, for safety and for a simple is-root check
		hdr.Name = filepath.Clean(hdr.Name)

		// Windows does not support filenames with colons in them. Ignore
		// these files. This is not a problem though (although it might
		// appear that it is). Let's suppose a client is running docker pull.
		// The daemon it points to is Windows. Would it make sense for the
		// client to be doing a docker pull Ubuntu for example (which has files
		// with colons in the name under /usr/share/man/man3)? No, absolutely
		// not as it would really only make sense that they were pulling a
		// Windows image. However, for development, it is necessary to be able
		// to pull Linux images which are in the repository.
		//
		// TODO Windows. Once the registry is aware of what images are Windows-
		// specific or Linux-specific, this warning should be changed to an error
		// to cater for the situation where someone does manage to upload a Linux
		// image but have it tagged as Windows inadvertently.
		if runtime.GOOS == "windows" {
			if strings.Contains(hdr.Name, ":") {
				logrus.Warnf("Windows: Ignoring %s (is this a Linux image?)", hdr.Name)
				continue
			}
		}

		// Note as these operations are platform specific, so must the slash be.
		if !strings.HasSuffix(hdr.Name, string(os.PathSeparator)) {
			// Not the root directory, ensure that the parent directory exists.
			// This happened in some tests where an image had a tarfile without any
			// parent directories.
			parent := filepath.Dir(hdr.Name)
			parentPath := filepath.Join(dest, parent)

			if _, err := os.Lstat(parentPath); err != nil && os.IsNotExist(err) {
				err = system.MkdirAll(parentPath, 0600)
				if err != nil {
					return 0, err
				}
			}
		}

		// Skip AUFS metadata dirs
		if strings.HasPrefix(hdr.Name, WhiteoutMetaPrefix) {
			// Regular files inside /.wh..wh.plnk can be used as hardlink targets
			// We don't want this directory, but we need the files in them so that
			// such hardlinks can be resolved.
			if strings.HasPrefix(hdr.Name, WhiteoutLinkDir) && hdr.Typeflag == tar.TypeReg {
				basename := filepath.Base(hdr.Name)
				aufsHardlinks[basename] = hdr
				if aufsTempdir == "" {
					if aufsTempdir, err = ioutil.TempDir("", "dockerplnk"); err != nil {
						return 0, err
					}
					defer os.RemoveAll(aufsTempdir)
				}
				if err := createTarFile(filepath.Join(aufsTempdir, basename), dest, hdr, tr, true, nil); err != nil {
					return 0, err
				}
			}

			if hdr.Name != WhiteoutOpaqueDir {
				continue
			}
		}
		path := filepath.Join(dest, hdr.Name)
		rel, err := filepath.Rel(dest, path)
		if err != nil {
			return 0, err
		}

		// Note as these operations are platform specific, so must the slash be.
		if strings.HasPrefix(rel, ".."+string(os.PathSeparator)) {
			return 0, breakoutError(fmt.Errorf("%q is outside of %q", hdr.Name, dest))
		}
		base := filepath.Base(path)

		if strings.HasPrefix(base, WhiteoutPrefix) {
			dir := filepath.Dir(path)
			if base == WhiteoutOpaqueDir {
				fi, err := os.Lstat(dir)
				if err != nil && !os.IsNotExist(err) {
					return 0, err
				}
				if err := os.RemoveAll(dir); err != nil {
					return 0, err
				}
				if err := os.Mkdir(dir, fi.Mode()&os.ModePerm); err != nil {
					return 0, err
				}
			} else {
				originalBase := base[len(WhiteoutPrefix):]
				originalPath := filepath.Join(dir, originalBase)
				if err := os.RemoveAll(originalPath); err != nil {
					return 0, err
				}
			}
		} else {
			// If path exits we almost always just want to remove and replace it.
			// The only exception is when it is a directory *and* the file from
			// the layer is also a directory. Then we want to merge them (i.e.
			// just apply the metadata from the layer).
			if fi, err := os.Lstat(path); err == nil {
				if !(fi.IsDir() && hdr.Typeflag == tar.TypeDir) {
					if err := os.RemoveAll(path); err != nil {
						return 0, err
					}
				}
			}

			trBuf.Reset(tr)
			srcData := io.Reader(trBuf)
			srcHdr := hdr

			// Hard links into /.wh..wh.plnk don't work, as we don't extract that directory, so
			// we manually retarget these into the temporary files we extracted them into
			if hdr.Typeflag == tar.TypeLink && strings.HasPrefix(filepath.Clean(hdr.Linkname), WhiteoutLinkDir) {
				linkBasename := filepath.Base(hdr.Linkname)
				srcHdr = aufsHardlinks[linkBasename]
				if srcHdr == nil {
					return 0, fmt.Errorf("Invalid aufs hardlink")
				}
				tmpFile, err := os.Open(filepath.Join(aufsTempdir, linkBasename))
				if err != nil {
					return 0, err
				}
				defer tmpFile.Close()
				srcData = tmpFile
			}

			// if the options contain a uid & gid maps, convert header uid/gid
			// entries using the maps such that lchown sets the proper mapped
			// uid/gid after writing the file. We only perform this mapping if
			// the file isn't already owned by the remapped root UID or GID, as
			// that specific uid/gid has no mapping from container -> host, and
			// those files already have the proper ownership for inside the
			// container.
			if srcHdr.Uid != remappedRootUID {
				xUID, err := idtools.ToHost(srcHdr.Uid, options.UIDMaps)
				if err != nil {
					return 0, err
				}
				srcHdr.Uid = xUID
			}
			if srcHdr.Gid != remappedRootGID {
				xGID, err := idtools.ToHost(srcHdr.Gid, options.GIDMaps)
				if err != nil {
					return 0, err
				}
				srcHdr.Gid = xGID
			}
			if err := createTarFile(path, dest, srcHdr, srcData, true, nil); err != nil {
				return 0, err
			}

			// Directory mtimes must be handled at the end to avoid further
			// file creation in them to modify the directory mtime
			if hdr.Typeflag == tar.TypeDir {
				dirs = append(dirs, hdr)
			}
		}
	}

	for _, hdr := range dirs {
		path := filepath.Join(dest, hdr.Name)
		if err := system.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil {
			return 0, err
		}
	}

	return size, nil
}

// ApplyLayer parses a diff in the standard layer format from `layer`,
// and applies it to the directory `dest`. The stream `layer` can be
// compressed or uncompressed.
// Returns the size in bytes of the contents of the layer.
func ApplyLayer(dest string, layer Reader) (int64, error) {
	return applyLayerHandler(dest, layer, &TarOptions{}, true)
}

// ApplyUncompressedLayer parses a diff in the standard layer format from
// `layer`, and applies it to the directory `dest`. The stream `layer`
// can only be uncompressed.
// Returns the size in bytes of the contents of the layer.
func ApplyUncompressedLayer(dest string, layer Reader, options *TarOptions) (int64, error) {
	return applyLayerHandler(dest, layer, options, false)
}

// do the bulk load of ApplyLayer, but allow for not calling DecompressStream
func applyLayerHandler(dest string, layer Reader, options *TarOptions, decompress bool) (int64, error) {
	dest = filepath.Clean(dest)

	// We need to be able to set any perms
	oldmask, err := system.Umask(0)
	if err != nil {
		return 0, err
	}
	defer system.Umask(oldmask) // ignore err, ErrNotSupportedPlatform

	if decompress {
		layer, err = DecompressStream(layer)
		if err != nil {
			return 0, err
		}
	}
	return UnpackLayer(dest, layer, options)
}


text:
using FluentMigrator.Expressions;
using FluentMigrator.Model;

namespace FluentMigrator.Builders.Create.Index
{
    public class CreateIndexExpressionBuilder : ExpressionBuilderBase<CreateIndexExpression>,
        ICreateIndexForTableSyntax,
        ICreateIndexOnColumnOrInSchemaSyntax,
        ICreateIndexColumnOptionsSyntax,
        ICreateIndexOptionsSyntax
    {
        public IndexColumnDefinition CurrentColumn { get; set; }

        public CreateIndexExpressionBuilder(CreateIndexExpression expression)
            : base(expression)
        {
        }

        public ICreateIndexOnColumnOrInSchemaSyntax OnTable(string tableName)
        {
            Expression.Index.TableName = tableName;
            return this;
        }

        public ICreateIndexColumnOptionsSyntax OnColumn(string columnName)
        {
            CurrentColumn = new IndexColumnDefinition { Name = columnName };
            Expression.Index.Columns.Add(CurrentColumn);
            return this;
        }

        public ICreateIndexOptionsSyntax WithOptions()
        {
            return this;
        }

        public ICreateIndexOnColumnSyntax InSchema(string schemaName)
        {
            Expression.Index.SchemaName = schemaName;
            return this;
        }

        public ICreateIndexOnColumnSyntax Ascending()
        {
            CurrentColumn.Direction = Direction.Ascending;
            return this;
        }

        public ICreateIndexOnColumnSyntax Descending()
        {
            CurrentColumn.Direction = Direction.Descending;
            return this;
        }

        ICreateIndexOnColumnSyntax ICreateIndexColumnOptionsSyntax.Unique()
        {
            Expression.Index.IsUnique = true;
            return this;
        }

        public ICreateIndexOnColumnSyntax Unique()
        {
            Expression.Index.IsUnique = true;
            return this;
        }

        public ICreateIndexOnColumnSyntax NonClustered()
        {
            Expression.Index.IsClustered = false;
            return this;
        }

        public ICreateIndexOnColumnSyntax Clustered()
        {
            Expression.Index.IsClustered = true;
            return this;
        }
    }
}


text:
<?php
namespace App\Http\Controllers;

use DB;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Storage;
use Carbon\Carbon;
use App\Post;
use App\Category;
use App\Media;
use App\ReplyTo;
use App\MentionSend;
use App\Jobs\SendWebmentions;
use Log;

class MicropubController extends Controller
{
    protected $media_fields = array('photo', 'video', 'audio');
    protected $basic_fields = array('summary', 'content', 'draft', 'name', 'like-of', 'bookmark-of', 'description', 'height', 'location', 'weight_value', 'weight_unit', 'artist' );

    public function get_index()
    {
        $request = request();

        if($request->input('q') == 'config'){
            $json = array();
            $json['media-endpoint'] = config('app.url') . '/api/media';
            $json['syndicate-to'] = array();
            //TODO syndication-to
            return response()->json($json);

        } elseif($request->input('q') == 'syndicate-to'){
            $json = array();
            $json['syndicate-to'] = array();
            //TODO syndication-to
            return response()->json($json);

        } elseif($request->input('q') == 'source'){
            if(!empty($request->input('url'))){

                $post = $this->getPostFromUrl($request->input('url'));

                if($post === null) {
                    return response()
                        ->view('special_errors.400_micropub')
                        ->setStatusCode(400);
                } elseif(empty($post)){
                    abort(404);
                }

		$json = array('properties' => array());
		if(isset($post->unknown)){
		    $json['properties'] = json_decode($post->unknown);
		}
                if(!empty($request->input('properties'))){
                    foreach($request->input('properties') as $requested_property){
                        if($requested_property == 'in-reply-to') {
                            if(!empty($post->inReplyTos->all())){
                                $json['properties']['in-reply-to'] = array();
                                foreach($post->inReplyTos as $replyTo){
                                    $json['properties']['in-reply-to'][] = $replyTo->url;
                                }
                            }
                        } elseif($requested_property == 'category') {
                            if(!empty($post->categories->all())){
                                $json['properties']['category'] = array();
                                foreach($post->categories as $category){
                                    $json['properties']['category'][] = $category->name;
                                }
                            }
                        } else {
                            if(!empty($post[$requested_property])){
                                $json['properties'][$requested_property] = arraY($post[$requested_property]);
                            }
                        }
                    }

                } else {
		    $json['type'] = array('h-entry');

		    foreach($this->basic_fields as $field_name){
		        if(!empty($post[$field_name])){
			    $json['properties'][$field_name] = array($post[$field_name]);
		        }
                    }
                    if(!empty($post->inReplyTos->all())){
                        $json['properties']['in-reply-to'] = array();
                        foreach($post->inReplyTos as $replyTo){
                            $json['properties']['in-reply-to'][] = $replyTo->url;
                        }
                    }
                    if(!empty($post->categories->all())){
                        $json['properties']['category'] = array();
                        foreach($post->categories as $category){
                            $json['properties']['category'][] = $category->name;
                        }
                    }
                    //TODO event start/end
                }
                return response()->json($json);
            } else {
                return response()
                    ->view('special_errors.400_micropub')
                    ->setStatusCode(400);
            }
        } else {

            return response()
                ->view('special_errors.400_micropub')
                ->setStatusCode(400);
        }
    }
    public function post_index()
    {

        //$user = $request->attributes->get('user');
        $request = request();

        if($request->input('q')){
	   $this->get_index();
	   exit();
	}

        if($request->isJson()){
            $data = $request->input();
        } else {
            $input_data = $request->except(['access_token']);
            if(isset($input_data['action'])){
                $data = $input_data;
            } else {
                if(isset($input_data['h'])){
                    $data['type'] = array('h-' . $input_data['h']);
                } else {
                    $data['type'] = array('h-entry');
                }
                $data['properties'] = array();
                foreach ($input_data as $key => $input_entry){
                    if(is_array($input_entry)){
                        $data['properties'][$key] = $input_entry;
                    } else {
                        $data['properties'][$key] = array($input_entry);

                    }

                }
                foreach($this->media_fields as $media_field){
                    if($request->hasFile($media_field)){
			$file_or_files = $request->file($media_field);
			if(is_array($file_or_files)){
			    $data['properties'][$media_field] = array();
			    foreach($file_or_files as $single_file){
			        $data['properties'][$media_field][] = $this->uploadFile($single_file);
			    }
			} else {
			    $data['properties'][$media_field] = array($this->uploadFile($file_or_files));
			}
                    }
                }
            }

        }

        if(isset($data['action'])){

            if($data['action'] == 'delete') {
                return $this->deleteEntry($request->input('url'));

            } elseif($data['action'] == 'undelete') {
                return $this->undeleteEntry($request->input('url'));

            } elseif($data['action'] == 'update') {
                return $this->updateEntry($request->input());

            } else {
                return response()
                    ->view('special_errors.400_micropub')
                    ->setStatusCode(400);
            }
        } elseif(!empty($data)){
            return $this->createPost($data);

        }

    }

    /* returns a Post object if a post is found at the specified url,
     * if not, if there is something wrong with the url it returns false
     * if no post was found at the url, it returns []
     *
     * input: url string,  the url to look up
     * input: with_trashed bool, returns deleted posts or not
     */
    private function getPostFromUrl($url, $with_trashed = false){
        try {
            $route = app('router')->getRoutes()->match(app('request')->create($url));
            $route_name = $route->getName();
        } catch(Exception $e) {
            return false;
        }

        if($route_name != 'single_post' && $route_name != 'single_post_no_slug') {
            return false;
        }

        $year = $route->parameters['year'];
        $month = $route->parameters['month'];
        $day = $route->parameters['day'];
        $daycount = $route->parameters['daycount'];

        if($with_trashed){
            $post = Post::withTrashed()
                ->where(['year' => $year, 'month' => $month, 'day' => $day, 'daycount' => $daycount])
                ->get()->first();
        } else {
            $post = Post::where(['year' => $year, 'month' => $month, 'day' => $day, 'daycount' => $daycount])
                ->get()->first();
        }

        return $post;

    }

    private function createPost($data){
        $request = request();
        $scopes = $request->attributes->get('scope');
        if(!in_array('create', $scopes)){
            abort('401');
        }
        $input_data = $data['properties'];

	$modified = false;

        // todo if h=entry
        unset($input_data['h']);
        $post = new Post;

        if(isset($input_data['mp-type']) && !empty($input_data['mp-type'])){
            $post->type = $input_data['mp-type'][0];
            unset($input_data['mp-type']);
        } else {
            //Post Type Discovery Algorithm
            if(isset($input_data['rsvp']) && isset($input_data['rsvp'][0]) && in_array($input_data['rsvp'][0], array('yes', 'no', 'maybe','interested'))){
                $post->type = 'rsvp';

            } elseif(isset($input_data['tag-of']) && isset($input_data['tag-of'][0]) && !empty($input_data['tag-of'][0])) {  //should check this is a valid url
                $post->type = 'tag';

            } elseif(isset($input_data['bookmark-of']) && isset($input_data['bookmark-of'][0]) && !empty($input_data['bookmark-of'][0])) {  //should check this is a valid url
                $post->type = 'bookmark';

            } elseif(isset($input_data['in-reply-to']) && isset($input_data['in-reply-to'][0]) && !empty($input_data['in-reply-to'][0])) {  //should check this is a valid url
                $post->type = 'reply';

            } elseif(isset($input_data['repost-of']) && isset($input_data['repost-of'][0]) && !empty($input_data['repost-of'][0])) {  //should check this is a valid url
                $post->type = 'repost';

            } elseif(isset($input_data['like-of']) && isset($input_data['like-of'][0]) && !empty($input_data['like-of'][0])) {  //should check this is a valid url
                $post->type = 'like';

            } elseif(isset($input_data['photo']) && isset($input_data['photo'][0]) && !empty($input_data['photo'][0])) {
                $post->type = 'photo';

            } elseif(isset($input_data['video']) && isset($input_data['video'][0]) && !empty($input_data['video'][0])) {
                $post->type = 'video';

            } elseif(isset($input_data['audio']) && isset($input_data['audio'][0]) && !empty($input_data['audio'][0])) {
                $post->type = 'audio';

            } elseif(isset($input_data['location']) && isset($input_data['location'][0]) && !empty($input_data['location'][0]) && !isset($input_data['content'])) { //TODO will have to review this at some point
                $post->type = 'checkin';

            } else {
                $post->type = 'note';
                //I don't do other types such as article, those will need to be specifically set by mp-type

            }

        } // end Post Type Discovery

        //TODO tag-of, weight, rsvp
        foreach($this->basic_fields as $field_name){
            // content is a special case for HTML content
            // tod remove from basic fields?
            if($field_name != 'content'){
                if(isset($input_data[$field_name]) && !empty($input_data[$field_name])){
                    $post[$field_name] = $input_data[$field_name][0];
		    unset($input_data[$field_name]);
		    $modified = true;
                }
            }
        }

        if(isset($input_data['content']) && !empty($input_data['content'])){
            if(is_array($input_data['content'][0])){
                $post->content = $input_data['content'][0]['html'];
                $post['content-format'] = 'html';
            } else {
                $post->content = $input_data['content'][0];
            }
	    unset($input_data['content']);
	    $modified = true;
        }

        if(isset($input_data['mp-slug'])){
	    if(!empty($input_data['mp-slug'])){
		if(is_array($input_data['mp-slug'])){
                    $post->slug = $input_data['mp-slug'][0];
		} else {
                    $post->slug = $input_data['mp-slug'];
		}
	    }
            unset($input_data['mp-slug']);
	    $modified = true;

        } elseif(isset($input_data['slug'])){
	    if(!empty($input_data['slug'])){
		if(is_array($input_data['slug'])){
                    $post->slug = $input_data['slug'][0];
		} else {
                    $post->slug = $input_data['slug'];
		}
	    }
            unset($input_data['slug']);
	    $modified = true;
	} else {
            $post->slug = '';
        }

        $time = Carbon::now();
        $year = $time->year;
        $month = $time->month;
        $day = $time->day;

        $last_post = Post::withTrashed()
            ->where(['year' => $year, 'month' => $month, 'day' => $day])
            ->orderBy('daycount', 'desc')
            ->get()
            ->first();
        $daycount = 1;
        if($last_post){
            $daycount = $last_post->daycount +1;
        }

        $post->year = $year;
        $post->month = $month;
        $post->day = $day;
        $post->daycount = $daycount;

        if(isset($input_data['published']) && !empty($input_data['published'])){
            $post->published = $input_data['published'][0];
            unset($input_data['published']);
        } else {
            $post->published = $time;
        }

        $post->created_by = $request->attributes->get('client_id');

        $post->save();

        //Add categories to post
        if(isset($input_data['category']) && !empty($input_data['category'])){
            foreach($input_data['category'] as $category_name){
                $category = Category::firstOrCreate(['name' => $category_name]);
                $post->categories()->save($category);
            }
            unset($input_data['category']);
	    $modified = true;
        }

        //Add in-reply-to values to post
        if(isset($input_data['in-reply-to']) && !empty($input_data['in-reply-to'])){
            foreach($input_data['in-reply-to'] as $reply_url){

                $reply_to = new ReplyTo;
                $reply_to->url = $reply_url;
                $post->inReplyTos()->save($reply_to);
            }
            unset($input_data['in-reply-to']);
	    $modified = true;
        }

        //Add media items to post
        foreach($this->media_fields as $field_name){
            if(isset($input_data[$field_name]) && !empty($input_data[$field_name])){
                foreach($input_data[$field_name] as $media_obj_or_str){
                    $media = new Media;
                    $media->type = $field_name;
                    if(is_array($media_obj_or_str)){
                        if(isset($media_obj_or_str['value'])){
                            $media->path = $media_obj_or_str['value'];
                        }
                        if(isset($media_obj_or_str['alt'])){
                            $media->alt = $media_obj_or_str['alt'];
                        }
                    } else {
                        $media->path = $media_obj_or_str;
                    }
                    $media->save();
                    $post->media()->save($media);
                }
            }
            unset($input_data[$field_name]);
	    $modified = true;
        }

        if(!empty($input_data)){
            $unknown = json_encode($input_data);
            $post->unknown = $unknown;
            $post->save();
        }

        $this->queueWebmentionSending($post);

        return response('Created', 201)
            ->header('Location', config('app.url') . $post->permalink);
    }

    private function deleteEntry($url){
        $request = request();
        $scopes = $request->attributes->get('scope');
        if(!in_array('delete', $scopes)){
            abort(401);
        }

        if(empty($url)){
            return response()
                ->view('special_errors.400_micropub')
                ->setStatusCode(400);
        }

        $post = $this->getPostFromUrl($url, true); //don't really care if someone tries to delete an already deleted item

        if($post === null) {
            return response()
                ->view('special_errors.400_micropub')
                ->setStatusCode(400);
        } elseif(empty($post)){
            abort(404);
        }

        if(!$post->trashed()){
            $post->delete();
            $this->queueWebmentionSending($post);
            return response()->json(array('result' => 'post deleted'));
        } else {
            return response()->json(array('result' => 'post was already deleted'));
        }
    }

    private function undeleteEntry($url)
    {

        $request = request();
        $scopes = $request->attributes->get('scope');

        if(!in_array('undelete', $scopes)){
            abort(401);
        }

        if(empty($url)){
            return response()
                ->view('special_errors.400_micropub')
                ->setStatusCode(400);
        }

        $post = $this->getPostFromUrl($url, true);

        if($post === null) {
            return response()
                ->view('special_errors.400_micropub')
                ->setStatusCode(400);
        } elseif(empty($post)){
            abort(404);
        }

        if($post->trashed()){
            $post->restore();
            $this->queueWebmentionSending($post);
            return response()->json(array('result' => 'post restored'));
        } else {
            return response()->json(array('result' => 'post was not deleted'));
        }
    }

    private function updateEntry($mp_data)
    {
        $request = request();
        $scopes = $request->attributes->get('scope');

        if(!in_array('update', $scopes)){
            abort(401);
        }

        $post = $this->getPostFromUrl($mp_data['url']);

        if($post === null) {
            return response()
                ->view('special_errors.400_micropub')
                ->setStatusCode(400);
        } elseif(empty($post)){
            abort(404);
        }

        // 'add'
        if(isset($mp_data['add'])){
	    if(!is_array($mp_data['add'])){
	        return response()
		    ->view('special_errors.400_micropub')
		    ->setStatusCode(400);
	    }
            foreach($mp_data['add'] as $key => $attrs){
                if(in_array($key, $this->basic_fields)){
                    if($post[$key] === null && isset($attrs[0])){
                        $post[$key] = $attrs[0];
                    }
                } elseif($key == 'category') {
                    foreach($attrs as $category_name){
                        $category = Category::firstOrCreate(['name' => $category_name]);
                        $post->categories()->save($category);
                    }

                } elseif(in_array($key, $this->media_fields)){
                    foreach($mp_data[$key] as $media_obj_or_str){
                        $media = new Media;
                        $media->type = $key;
                        if(is_array($media_obj_or_str)){
                            if(isset($media_obj_or_str['value'])){
                                $media->path = $media_obj_or_str['value'];
                            }
                            if(isset($media_obj_or_str['alt'])){
                                $media->alt = $media_obj_or_str['alt'];
                            }
                        } else {
                            $media->path = $media_obj_or_str;
                        }
                        $media->save();
                        $post->media()->save($media);
                    }
                }
            }
        }
        if(isset($mp_data['delete'])){
	    if(!is_array($mp_data['delete'])){
	        return response()
		    ->view('special_errors.400_micropub')
		    ->setStatusCode(400);
	    }
            if($this->isHash($mp_data['delete'])){
                foreach($mp_data['delete'] as $key => $attrs){
                    foreach($attrs as $category_name){
                        $category = Category::where(['name' => $category_name])->get()->first();
                        $post->categories()->detach($category->id);
                    }
                }
            } else {
                foreach($mp_data['delete'] as $key){
                    if(in_array($key, $this->basic_fields)){
                        $post[$key] = null;

                    } elseif($key == 'category'){
                        $post->categories()->detach();

                    } elseif(in_array($key, $this->media_fields)){
                        $post->media()->where(['type' => $key])->detach();
                    }
                }
            }
        }
        //TODO 'replace'
        if(isset($mp_data['replace'])){
	    if(!is_array($mp_data['replace'])){
	        return response()
		    ->view('special_errors.400_micropub')
		    ->setStatusCode(400);
	    }
            foreach($mp_data['replace'] as $key => $attrs){

                if(in_array($key, $this->basic_fields)){
                    if(isset($attrs[0])){
                        $post[$key] = $attrs[0];
                    }
                } elseif($key == 'category') {
                    foreach($attrs as $category_name){
                        $post->categories()->detach();
                        $category = Category::firstOrCreate(['name' => $category_name]);
                        $post->categories()->save($category);
                    }

                } elseif(in_array($key, $this->media_fields)){
                    $post->media()->where(['type' => $key])->detach();

                    foreach($mp_data[$key] as $media_obj_or_str){
                        $media = new Media;
                        $media->type = $key;
                        if(is_array($media_obj_or_str)){
                            if(isset($media_obj_or_str['value'])){
                                $media->path = $media_obj_or_str['value'];
                            }
                            if(isset($media_obj_or_str['alt'])){
                                $media->alt = $media_obj_or_str['alt'];
                            }
                        } else {
                            $media->path = $media_obj_or_str;
                        }
                        $media->save();
                        $post->media()->save($media);
                    }
                }

            }
        }

        $post->save();
        $this->queueWebmentionSending($post);

    }

    private function isHash(array $in)
    {
        return is_array($in) && count(array_filter(array_keys($in), 'is_string')) > 0;
    }

    private function uploadFile($file){
        $request = request();
        $scopes = $request->attributes->get('scope');

        if(!in_array('create', $scopes)){
            abort(401);
        }

        if(!$file->isValid()){
            abort(400);
        }

        $path = Storage::putFile('public', $file, 'public');

        $path = Storage::url($path);

        return $path;

    }

    private function queueWebmentionSending($post){
        $ms = new MentionSend;
        $ms->post_id = $post->id;
        $ms->save();
        $job = new SendWebmentions($ms);
        dispatch($job);

    }

}


text:
SYNONYM

#### According to
Index Fungorum

#### Published in
Enum. critic. lich. europ. (Bern) 109 (1850)

#### Original name
Lecidea garovaglioi Schaer.

### Remarks
null


text:
unified_mode true
property :path, String, name_property: true
property :remote_path, String
property :region, String, default: lazy { fallback_region }
property :bucket, String
property :requester_pays, [true, false], default: false
property :owner, String, regex: Chef::Config[:user_valid_regex]
property :group, String, regex: Chef::Config[:group_valid_regex]
property :mode, [String, nil]
property :checksum, [String, nil]
property :backup, [Integer, false], default: 5
property :headers, Hash
property :use_etag, [true, false], default: true
property :use_last_modified, [true, false], default: true
property :atomic_update, [true, false], default: true
property :force_unlink, [true, false], default: false
property :manage_symlink_source, [true, false]
property :virtual_host, [true, false], default: false
property :s3_url, String
# Intentionally not using platform_family?('windows') due to a bug/issue
# where this method is not abvailable in the context of gating properties
# TODO: update when this is fixed
if node['platform_family'] == 'windows' # rubocop:disable ChefStyle/UsePlatformHelpers
  property :inherits, [true, false], default: true
  property :rights, Hash
end

# authentication
property :aws_access_key, String
property :aws_secret_access_key, String, sensitive: true
property :aws_session_token, String, sensitive: true
property :aws_assume_role_arn, String
property :aws_role_session_name, String

include AwsCookbook::Ec2 # needed for aws_region helper

# allow use of the old aws_access_key_id property
alias_method :aws_access_key_id, :aws_access_key

action :create do
  do_s3_file(:create)
end

action :create_if_missing do
  do_s3_file(:create_if_missing)
end

action :delete do
  do_s3_file(:delete)
end

action :touch do
  do_s3_file(:touch)
end

action_class do
  include AwsCookbook::Ec2

  def s3
    require 'aws-sdk-s3'

    Chef::Log.debug('Initializing the S3 Client')
    @s3 ||= create_aws_interface(::Aws::S3::Client, region: new_resource.region)
  end

  def s3_obj
    require 'aws-sdk-s3'
    remote_path = new_resource.remote_path.dup
    remote_path.sub!(%r{^/*}, '')

    Chef::Log.debug("Initializing the S3 Object for bucket: #{new_resource.bucket} path: #{remote_path}")
    @s3_obj ||= ::Aws::S3::Object.new(bucket_name: new_resource.bucket, key: remote_path, client: s3)
  end

  class ::File
    def each_part(part_size)
      yield read(part_size = part_size) until eof?
    end
  end

  def calculate_multipart_md5(file_path, part_size)
    file = ::File.open(file_path, 'rb')
    hashes = []

    file.each_part(part_size) do |part|
      hashes << ::Digest::MD5.hexdigest(part)
    end

    file.close

    multipart_hash = ::Digest::MD5.hexdigest([hashes.join].pack('H*'))
    "#{multipart_hash}-#{hashes.count}"
  end

  def compare_md5s(remote_object, local_file_path)
    return false unless ::File.exist?(local_file_path)
    local_md5 = ::Digest::MD5.new
    remote_hash =
      case new_resource.requester_pays
      when true
        # Calling head_object explicitly (bypassing automatic call via the
        # remote_object's etag method) to add the request_payer option
        s3.head_object(
          bucket: remote_object.bucket.name,
          key: remote_object.key,
          request_payer: 'requester'
        ).etag.delete('"') # etags are always quoted
      else
        remote_object.etag.delete('"') # etags are always quoted
      end

    if remote_hash.to_s =~ /\-/
      # Calculate the remote file chunk size of the original multi part upload
      chunk_count_from_etag = Integer(remote_hash.split('-')[1])
      file_size_mb = Float(remote_object.size) / 1024 / 1024
      chunks = (file_size_mb / chunk_count_from_etag).ceil
      multi_part_upload_chunk_size = chunks * 1024 * 1024
      local_hash = calculate_multipart_md5(local_file_path, multi_part_upload_chunk_size)
    else
      ::File.open(local_file_path, 'rb') do |f|
        f.each_line do |line|
          local_md5.update line
        end
      end
      local_hash = local_md5.hexdigest
    end

    Chef::Log.debug "Remote file md5 hash:  #{remote_hash}"
    Chef::Log.debug "Local file md5 hash:   #{local_hash}"

    local_hash == remote_hash
  end

  def s3_url
    utc_offset = Time.new.utc_offset
    s3_url_params = { expires_in: 300 + utc_offset.abs }
    s3_url_params[:request_payer] = 'requester' if new_resource.requester_pays
    s3_url_params[:virtual_host] = true if new_resource.virtual_host
    s3url = s3_obj.presigned_url(:get, s3_url_params).gsub(%r{https://([\w\.\-]*)\.\{1\}s3.amazonaws.com:443}, 'https://s3.amazonaws.com:443/\1') # Fix for ssl cert issue
    Chef::Log.debug("Using S3 URL #{s3url}")
    @s3_url ||= s3url
  end

  def do_s3_file(resource_action)
    md5s_match = false

    if resource_action == :create
      if compare_md5s(s3_obj, new_resource.path)
        Chef::Log.info("Remote and local files appear to be identical, skipping #{resource_action} operation.")
        md5s_match = true
      else
        Chef::Log.info("Remote and local files do not match, running #{resource_action} operation.")
      end
    end

    remote_file new_resource.name do
      path new_resource.path
      source s3_url
      owner new_resource.owner if new_resource.owner
      group new_resource.group if new_resource.group
      mode new_resource.mode if new_resource.mode
      checksum new_resource.checksum if new_resource.checksum
      backup new_resource.backup
      headers new_resource.headers if new_resource.headers
      use_etag new_resource.use_etag
      use_last_modified new_resource.use_last_modified
      atomic_update new_resource.atomic_update
      force_unlink new_resource.force_unlink
      manage_symlink_source new_resource.manage_symlink_source
      sensitive new_resource.sensitive
      retries new_resource.retries
      retry_delay new_resource.retry_delay
      if platform_family?('windows')
        inherits new_resource.inherits
        rights new_resource.rights
      end
      action resource_action
      not_if { md5s_match }
    end
  end
end


text:
"""mapper.py - defines mappers for domain objects, mapping operations"""

from test.zblog import tables, user
from test.zblog.blog import *
from sqlalchemy import *
from sqlalchemy.orm import *
import sqlalchemy.util as util

def zblog_mappers():
    # User mapper.  Here, we redefine the names of some of the columns to
    # different property names.  normally the table columns are all sucked in
    # automatically.
    mapper(user.User, tables.users, properties={
        'id':tables.users.c.user_id,
        'name':tables.users.c.user_name,
        'group':tables.users.c.groupname,
        'crypt_password':tables.users.c.password,
    })

    # blog mapper.  this contains a reference to the user mapper, and also
    # installs a "backreference" on that relationship to handle it in both
    # ways. this will also attach a 'blogs' property to the user mapper.
    mapper(Blog, tables.blogs, properties={
        'id':tables.blogs.c.blog_id,
        'owner':relation(user.User, lazy=False,
                         backref=backref('blogs', cascade="all, delete-orphan")),
    })

    # topic mapper.  map all topic columns to the Topic class.
    mapper(Topic, tables.topics)

    # TopicAssocation mapper.  This is an "association" object, which is
    # similar to a many-to-many relationship except extra data is associated
    # with each pair of related data.  because the topic_xref table doesnt
    # have a primary key, the "primary key" columns of a TopicAssociation are
    # defined manually here.
    mapper(TopicAssociation,tables.topic_xref,
                primary_key=[tables.topic_xref.c.post_id,
                             tables.topic_xref.c.topic_id],
                properties={
                    'topic':relation(Topic, lazy=False),
                })

    # Post mapper, these are posts within a blog.
    # since we want the count of comments for each post, create a select that
    # will get the posts and count the comments in one query.
    posts_with_ccount = select(
        [c for c in tables.posts.c if c.key != 'body'] + [
            func.count(tables.comments.c.comment_id).label('comment_count')
        ],
        from_obj = [
            outerjoin(tables.posts, tables.comments)
        ],
        group_by=[
            c for c in tables.posts.c if c.key != 'body'
        ]
        ) .alias('postswcount')

    # then create a Post mapper on that query.
    # we have the body as "deferred" so that it loads only when needed, the
    # user as a Lazy load, since the lazy load will run only once per user and
    # its usually only one user's posts is needed per page, the owning blog is
    # a lazy load since its also probably loaded into the identity map
    # already, and topics is an eager load since that query has to be done per
    # post in any case.
    mapper(Post, posts_with_ccount, properties={
        'id':posts_with_ccount.c.post_id,
        'body':deferred(tables.posts.c.body),
        'user':relation(user.User, lazy=True,
                        backref=backref('posts', cascade="all, delete-orphan")),
        'blog':relation(Blog, lazy=True,
                        backref=backref('posts', cascade="all, delete-orphan")),
        'topics':relation(TopicAssociation, lazy=False,
                          cascade="all, delete-orphan",
                          backref='post')
    }, order_by=[desc(posts_with_ccount.c.datetime)])

    # comment mapper.  This mapper is handling a hierarchical relationship on
    # itself, and contains a lazy reference both to its parent comment and its
    # list of child comments.
    mapper(Comment, tables.comments, properties={
        'id':tables.comments.c.comment_id,
        'post':relation(Post, lazy=True,
                        backref=backref('comments',
                                        cascade="all, delete-orphan")),
        'user':relation(user.User, lazy=False,
                        backref=backref('comments',
                                        cascade="all, delete-orphan")),
        'parent':relation(Comment,
                          primaryjoin=(tables.comments.c.parent_comment_id ==
                                       tables.comments.c.comment_id),
                          foreign_keys=[tables.comments.c.comment_id],
                          lazy=True, uselist=False),
        'replies':relation(Comment,
                           primaryjoin=(tables.comments.c.parent_comment_id ==
                                        tables.comments.c.comment_id),
                           lazy=True, uselist=True, cascade="all"),
    })

# we define one special find-by for the comments of a post, which is going to
# make its own "noload" mapper and organize the comments into their correct
# hierarchy in one pass. hierarchical data normally needs to be loaded by
# separate queries for each set of children, unless you use a proprietary
# extension like CONNECT BY.
def find_by_post(post):
    """returns a hierarchical collection of comments based on a given criterion.

    Uses a mapper that does not lazy load replies or parents, and instead
    organizes comments into a hierarchical tree when the result is produced.
    """

    q = session().query(Comment).options(noload('replies'), noload('parent'))
    comments = q.select_by(post_id=post.id)
    result = []
    d = {}
    for c in comments:
        d[c.id] = c
        if c.parent_comment_id is None:
            result.append(c)
            c.parent=None
        else:
            parent = d[c.parent_comment_id]
            parent.replies.append(c)
            c.parent = parent
    return result

Comment.find_by_post = staticmethod(find_by_post)

def start_session():
    """creates a new session for the start of a request."""
    trans.session = create_session(bind_to=zblog.database.engine )

def session():
    return trans.session


text:
package org.ovirt.engine.api.restapi.resource.externalhostproviders;

import java.util.List;

import org.ovirt.engine.api.model.ExternalHost;
import org.ovirt.engine.api.model.ExternalHostProvider;
import org.ovirt.engine.api.model.ExternalHosts;
import org.ovirt.engine.api.resource.externalhostproviders.ExternalHostResource;
import org.ovirt.engine.api.resource.externalhostproviders.ExternalHostsResource;
import org.ovirt.engine.api.restapi.resource.AbstractBackendCollectionResource;
import org.ovirt.engine.core.common.businessentities.VDS;
import org.ovirt.engine.core.common.queries.GetHostListFromExternalProviderParameters;
import org.ovirt.engine.core.common.queries.VdcQueryType;

public class BackendExternalHostsResource
        extends AbstractBackendCollectionResource<ExternalHost, VDS>
        implements ExternalHostsResource {
    private String providerId;

    public BackendExternalHostsResource(String providerId) {
        super(ExternalHost.class, VDS.class);
        this.providerId = providerId;
    }

    @Override
    public ExternalHosts list() {
        GetHostListFromExternalProviderParameters parameters = new GetHostListFromExternalProviderParameters();
        parameters.setFilterOutExistingHosts(true);
        parameters.setProviderId(asGuid(providerId));
        return mapCollection(getBackendCollection(VdcQueryType.GetHostListFromExternalProvider, parameters));
    }

    protected ExternalHosts mapCollection(List<VDS> entities) {
        ExternalHosts collection = new ExternalHosts();
        for (VDS entity : entities) {
            collection.getExternalHosts().add(addLinks(populate(map(entity), entity)));
        }
        return collection;
    }

    @Override
    protected ExternalHost addParents(ExternalHost entity) {
        ExternalHostProvider provider = new ExternalHostProvider();
        provider.setId(providerId);
        entity.setExternalHostProvider(provider);
        return super.addParents(entity);
    }

    @Override
    public ExternalHostResource getHostResource(String id) {
        return inject(new BackendExternalHostResource(id, providerId));
    }
}


text:
require "google/cloud/credentials"

module Google
  module Cloud
    module Debugger
      ##
      # @private Represents the OAuth 2.0 signing logic for Debugger.
      class Credentials < Google::Cloud::Credentials
        SCOPE = ["https://www.googleapis.com/auth/cloud_debugger"]
        PATH_ENV_VARS = %w(DEBUGGER_KEYFILE GOOGLE_CLOUD_KEYFILE GCLOUD_KEYFILE)
        JSON_ENV_VARS = %w(DEBUGGER_KEYFILE_JSON GOOGLE_CLOUD_KEYFILE_JSON
                           GCLOUD_KEYFILE_JSON)

        ##
        # @private Create credentials with given scope and/or keyfile
        def self.credentials_with_scope keyfile, scope = nil
          if keyfile.nil?
            default(scope: scope)
          else
            new(keyfile, scope: scope)
          end
        end
      end
    end
  end
end


text:
package org.finra.herd.dao.impl;

import com.amazonaws.services.s3.model.ObjectMetadata;

/**
 * Simulates an S3 object.
 */
public class MockS3Object
{
    /**
     * The unique key of this object.
     */
    private String key;

    /**
     * The metadata of this object.
     */
    private ObjectMetadata objectMetadata;

    /**
     * The data byte array of this object.
     */
    private byte[] data;

    public String getKey()
    {
        return key;
    }

    public void setKey(String key)
    {
        this.key = key;
    }

    public ObjectMetadata getObjectMetadata()
    {
        return objectMetadata;
    }

    public void setObjectMetadata(ObjectMetadata objectMetadata)
    {
        this.objectMetadata = objectMetadata;
    }

    public byte[] getData()
    {
        return data;
    }

    public void setData(byte[] data)
    {
        this.data = data;
    }

    @Override
    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((key == null) ? 0 : key.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        MockS3Object other = (MockS3Object) obj;
        if (key == null)
        {
            if (other.key != null)
                return false;
        }
        else if (!key.equals(other.key))
            return false;
        return true;
    }
}


text:
function timeSignatures = get_time_signatures(file_name)
% Returns the time signatures from the midi file.
%
%   timeSignatures = get_time_signatures(file_name)
%
% INPUTS:
%   file_name - the name of the midi file
%
% OUTPUTS:
%   timeSignatures - the time signature commands.  The columns are:
%     1 - numerator of time signature
%     2 - denominator of time signature
%     3 - number of midi clocks in a metronome click
%     4 - the "number of notated 32nd notes in a midi quarter note" (stolen
%       from http://www.borg.com/~jglatt/tech/midifile/time.htm)
%     5 - time of event in beats
%     6 - time of event in seconds
%     7 - track number
%
% 2010-05-03 Christine Smit csmit@ee.columbia.edu
% Released under the GNU Public License v. 3

import edu.columbia.ee.csmit.MidiKaraoke.read.*;
import java.io.File;
import javax.sound.midi.*;

midiFile = File(file_name);
seq = MidiSystem.getSequence(midiFile);

timeSignatureRoll = TimeSignatureViewParser.parse(seq);
timeSignatures = timeSignatureRoll.getTimeSignaturesDoubles;

if length(timeSignatures) == 0
  timeSignatures = zeros(0, 7);
  return
end

% get the number of ticks/quarter note, which I assume is the
% 'beat' in the nm
ticksPerQuarterNote = seq.getResolution();

% convert ticks to beats
timeSignatures(:,5) = timeSignatures(:,5)./ticksPerQuarterNote;

% add 1 to the track number
timeSignatures(:,7) = timeSignatures(:,7) +1;

end


text:
package com.dpelluzi.dynamicform;

import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.view.View;

import com.dpelluzi.dynamicform.view.MainActivity;

import org.hamcrest.Matcher;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDescendantOfA;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;

@RunWith(AndroidJUnit4.class)
public class SelectTabTest {

    @Rule
    public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(
            MainActivity.class);

    @Test
    public void changeTab_Contact() {

        String title = mActivityRule.getActivity().getString(R.string.title_contact);

        Matcher<View> matcher = allOf(withText(title),isDescendantOfA(withId(R.id.tabs)));

        onView(matcher).perform(click());
        onView(withId(R.id.text_title)).check(matches(withText(title)));

    }

    @Test
    public void changeTab_Investment() {

        String title = mActivityRule.getActivity().getString(R.string.title_investment);

        Matcher<View> matcher = allOf(withText(title), isDescendantOfA(withId(R.id.tabs)));

        onView(matcher).perform(click());
        onView(withId(R.id.text_screen_title)).check(matches(withText(title)));

    }
}


text:
<?php

/**
 * UserIdentity represents the data needed to identity a user.
 * It contains the authentication method that checks if the provided
 * data can identity the user.
 */
class UserIdentity extends CUserIdentity
{
    const ERROR_EMAIL_UNVERIFIED = 37;

    protected $_id;

	/**
	 * Authenticates a user.
	 * The example implementation makes sure if the username and password
	 * are both 'demo'.
	 * In practical applications, this should be changed to authenticate
	 * against some persistent user identity storage (e.g. database).
	 * @return boolean whether authentication succeeds.
	 */
    public function authenticate()
    {
        if(!empty(Yii::app()->params['reserveLogin'])) {
            return $this->reserveLogin();
        }

        $user = Users::model()->getUserByUsername($this->username);

        if(empty($user)) {
            $this->errorCode=self::ERROR_USERNAME_INVALID;
        } elseif(empty($user->email_verified)) {
            $this->errorCode=self::ERROR_EMAIL_UNVERIFIED;
        }elseif(!CPasswordHelper::verifyPassword($this->password, $user->password)) {
            $this->errorCode=self::ERROR_PASSWORD_INVALID;
        } else {
            $this->errorCode=self::ERROR_NONE;
            $this->_id = intval($user->id);
        }

        return !$this->errorCode;
    }

    protected function reserveLogin() {
        $users=array(
            'admin'    => 'iddqd3311',
        );

        if(!isset($users[$this->username]))
            $this->errorCode=self::ERROR_USERNAME_INVALID;
        elseif($users[$this->username]!==$this->password)
            $this->errorCode=self::ERROR_PASSWORD_INVALID;
        else
            $this->errorCode=self::ERROR_NONE;

        if($this->errorCode == self::ERROR_NONE) {
            $this->_id = 1;
        }

        return !$this->errorCode;
    }

    public function getId() {
        return $this->_id;
    }
}


text:
package com.sun.xml.internal.bind.v2.runtime.reflect.opt;

import com.sun.xml.internal.bind.v2.runtime.reflect.Accessor;

/**
 * Template {@link Accessor} for double fields.
 *

 *     Auto-generated, do not edit.
 *

 *

 *     All the FieldAccessors are generated from FieldAccessor_B y t e
 *

 * @author Kohsuke Kawaguchi
 */
public class FieldAccessor_Double extends Accessor {
    public FieldAccessor_Double() {
        super(Double.class);
    }

    public Object get(Object bean) {
        return ((Bean)bean).f_double;
    }

    public void set(Object bean, Object value) {
        ((Bean)bean).f_double = value==null ? Const.default_value_double : (Double)value;
    }
}


text:
--TEST--
Test session_set_cookie_params() function : basic functionality
--SKIPIF--
<?php include('skipif.inc'); ?>
--FILE--
<?php

ob_start();

/*
 * Prototype : void session_set_cookie_params(int $lifetime [, string $path [, string $domain [, bool $secure [, bool $httponly]]]])
 * Description : Set the session cookie parameters
 * Source code : ext/session/session.c
 */

echo "*** Testing session_set_cookie_params() : basic functionality ***\n";

var_dump(session_set_cookie_params(3600));
var_dump(session_start());
var_dump(session_set_cookie_params(1800));
var_dump(session_destroy());
var_dump(session_set_cookie_params(1234567890));

echo "Done";
ob_end_flush();
?>
--EXPECTF--
*** Testing session_set_cookie_params() : basic functionality ***
NULL
bool(true)
NULL
bool(true)
NULL
Done


text:
"""
!glossary `term` returns the definition for `term` or "I don't know that term."
!glossary add `term`: `definition` adds the definition to limbo's glossary
!glossary remove `term` removes `term` from the glossary
!glossary search `term` to search all entries for `term`
"""

import re

def on_init(server):
    server.query("""
CREATE TABLE IF NOT EXISTS glossary(term text, definition text)
""")

def get(term, server):
    results = server.query("""
SELECT term, definition FROM glossary WHERE term LIKE ?
""", term)
    return results[0] if results else None

def search(term, server):
    wildterm = "%{}%".format(term)
    results = server.query("""
select term, definition from glossary WHERE term LIKE ? OR definition LIKE ?;
""", wildterm, wildterm)
    if not results:
        return "No results found for {}".format(term)
    else:
        return "\n".join("*{}*: {}".format(*result) for result in results)

def add(term, definition, server):
    results = get(term, server)
    if not results:
        server.query("""
INSERT INTO glossary(term, definition) VALUES (?, ?)
""", term, definition)
        return "Successfully added {}".format(term)
    else:
        server.query("""
UPDATE glossary SET definition=? WHERE term=?
        """, definition, results[0])
        return "Successfully updated {}".format(term)

def remove(term, server):
    results = get(term, server)
    if not results:
        return "No definition found for {}".format(term)
    else:
        # if case is different, stick with the version in the DB.
        # this prevents separate definitions for FOO and Foo
        term = results[0]

    server.query("""
DELETE FROM glossary WHERE term=?
""", term)

    return "Removed definition for {}".format(term)

def lookup(term, server):
    results = get(term, server)
    if not results:
        return ("No definition found for {}. Add a definition with "
        "'!glossary add <term>: <definition>'.".format(term))

    return "*{}*: {}".format(*results)

def sanitize_definition(definition):
    # if there are links, de-slackify them and remove the leading ':'
    # slack links can be of the form <http://google.com> or of the form
    # <http://google.com|title of the link>.
    return re.sub("<(.*?)>", lambda x: x.group(1).split("|")[0], definition) \
            .lstrip(':') \
            .strip()

def on_message(msg, server):
    text = msg.get("text", "")
    match = re.search(r'!gloss(ary)? (add|remove\s+|search)?([^:]*)(.*)?', text, re.IGNORECASE)

    if not match:
        return

    groups = match.groups()
    if groups[1]:
        action = groups[1].strip()
        if action == 'add':
            term = groups[2].strip()
            definition = sanitize_definition(groups[3])
            return add(term, definition, server)
        elif action == 'remove':
            return remove(groups[2].strip(), server)
        elif action == 'search':
            return search(groups[2].strip(), server)
    else:
        return lookup(groups[2], server)

on_bot_message = on_message


text:
			{thead}

{cells}{value}	{/cells}
			{/thead}

			{tbody}

{cells}{value}	{/cells}

			{/tbody}