diff --git a/scripts/publish.sh b/scripts/publish.sh new file mode 100644 index 000000000..72f141f56 --- /dev/null +++ b/scripts/publish.sh @@ -0,0 +1,92 @@ +#!/bin/bash +# This is a simple script to push the deb package to our private corpnet feed +# +# Usage: publish_package.sh [deb file] +# Requires: Azure Cli installed (for uploading to blob storage) +# +# Environment Dependencies: +# $STORAGE_CONTAINER_NAME +# $STORAGE_ACCOUNT +# $STORAGE_KEY +# $REPO_ID + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +DEB_FILE=$1 +UPLOAD_JSON_FILE="package_upload.json" + +execute(){ + if ! validate_inputs; then + exit 1 + fi + + upload_deb_to_blob_storage + generate_repoclient_json + call_repo_client +} + +validate_inputs(){ + local ret=0 + if [[ ! -f "$DEB_FILE" ]]; then + echo "Error: .deb file does not exist" + ret=1 + fi + if [[ -z "$STORAGE_CONTAINER" ]]; then + echo "Error: STORAGE_CONTAINER environment variable not set" + ret=1 + fi + + if [[ -z "$STORAGE_ACCOUNT" ]]; then + echo "Error: STORAGE_ACCOUNT environment variable not set" + ret=1 + fi + + if [[ -z "$STORAGE_KEY" ]]; then + echo "Error: STORAGE_KEY environment variable not set" + ret=1 + fi + + return $ret +} + +upload_deb_to_blob_storage(){ + local deb_filename=$(basename $DEB_FILE) + azure storage blob upload $DEB_FILE $STORAGE_CONTAINER $deb_filename -a $STORAGE_ACCOUNT -k $STORAGE_KEY + + UPLOAD_URL="http://$STORAGE_ACCOUNT.blob.core.windows.net/$STORAGE_CONTAINER/$deb_filename" +} + +generate_repoclient_json(){ + # Clean any existing json file + rm -f $SCRIPT_DIR/$UPLOAD_JSON_FILE + + echo "{" >> "$SCRIPT_DIR/$UPLOAD_JSON_FILE" + echo " \"name\":\"$(_get_package_name)\"," >> "$SCRIPT_DIR/$UPLOAD_JSON_FILE" + echo " \"version\":\"$(_get_package_version)\"," >> "$SCRIPT_DIR/$UPLOAD_JSON_FILE" + echo " \"repositoryId\":\"$REPO_ID\"," >> "$SCRIPT_DIR/$UPLOAD_JSON_FILE" + echo " \"sourceUrl\":\"$UPLOAD_URL\"" >> "$SCRIPT_DIR/$UPLOAD_JSON_FILE" + echo "}" >> "$SCRIPT_DIR/$UPLOAD_JSON_FILE" +} + +call_repo_client(){ + $SCRIPT_DIR/repoapi_client.sh -addpkg $SCRIPT_DIR/$UPLOAD_JSON_FILE +} + +# Extract the package name from the .deb filename +_get_package_name(){ + local deb_filename=$(basename $DEB_FILE) + local package_name=${deb_filename%%_*} + + echo $package_name +} + +# Extract the package version from the .deb filename +_get_package_version(){ + local deb_filename=$(basename $DEB_FILE) + local package_version=${deb_filename#*_} + package_version=${package_version%-*} + + echo $package_version +} + +execute \ No newline at end of file diff --git a/scripts/repoapi_client.sh b/scripts/repoapi_client.sh new file mode 100644 index 000000000..72c576cf9 --- /dev/null +++ b/scripts/repoapi_client.sh @@ -0,0 +1,189 @@ +#!/bin/bash +# This is a VERY basic script for Create/Delete operations on repos and packages +# +# Environment Dependencies: +# $REPO_SERVER +# $REPO_USER +# $REPO_PASS + +cmd=$1 +urls=urls.txt +defaultPackageFile=new_package.json +defaultRepoFile=new_repo.json +repositoryId=$REPO_ID +server=$REPO_SERVER +user=$REPO_USER +pass=$REPO_PASS +protocol=https +port=443 +baseurl="$protocol://$user:$pass@$server:$port" + +echo $baseurl + +function BailIf +{ + if [ $1 -ne 0 ]; then + echo "Failure occurred communicating with $server" + exit 1 + fi +} + +# List packages, using $1 as a regex to filter results +function ListPackages +{ + curl -k "$baseurl/v1/packages" | sed 's/{/\n{/g' | egrep "$1" | sed 's/,/,\n/g' | sed 's/^"/\t"/g' + echo "" +} + +# Create a new Repo using the specified JSON file +function AddRepo +{ + repoFile=$1 + if [ -z $repoFile ]; then + echo "Error: Must specify a JSON-formatted file. Reference $defaultRepoFile.template" + exit 1 + fi + if [ ! -f $repoFile ]; then + echo "Error: Cannot create repo - $repoFile does not exist" + exit 1 + fi + packageUrl=$(grep "url" $repoFile | head -n 1 | awk '{print $2}' | tr -d ',') + echo "Creating new repo on $server [$packageUrl]" + curl -i -k "$baseurl/v1/repositories" --data @./$repoFile -H "Content-Type: application/json" + BailIf $? + echo "" +} + +# Upload a single package using the specified JSON file +function AddPackage +{ + packageFile=$1 + if [ -z $packageFile ]; then + echo "Error: Must specify a JSON-formatted file. Reference $defaultPackageFile.template" + exit 1 + fi + if [ ! -f $packageFile ]; then + echo "Error: Cannot add package - $packageFile does not exist" + exit 1 + fi + packageUrl=$(grep "sourceUrl" $packageFile | head -n 1 | awk '{print $2}') + echo "Adding package to $server [$packageUrl]" + curl -i -k "$baseurl/v1/packages" --data @./$packageFile -H "Content-Type: application/json" + BailIf $? + echo "" +} + +# Upload a single package by dynamically creating a JSON file using a provided URL +function AddPackageByUrl +{ + # Parse URL + url=$(echo "$1") + if [ -z $url ]; then + return + fi + escapedUrl=$(echo "$url" | sed 's/\//\\\//g') + set -- "$1" + oldIFS=$IFS + IFS="/"; declare -a splitUrl=($*) + index=${#splitUrl[@]} + let "index -= 1" + filename=${splitUrl[$index]} + set -- "$filename" + IFS="_"; declare -a splitFile=($*) + IFS=$oldIFS + pkgName=${splitFile[0]} + pkgVer=${splitFile[1]} + if [ -z $pkgName ] || [ -z $pkgVer ]; then + echo "ERROR parsing $url" + return + fi + # Create Package .json file + cp $defaultPackageFile.template $defaultPackageFile + sed -i "s/PACKAGENAME/$pkgName/g" $defaultPackageFile + sed -i "s/PACKAGEVERSION/$pkgVer/g" $defaultPackageFile + sed -i "s/PACKAGEURL/$escapedUrl/g" $defaultPackageFile + sed -i "s/REPOSITORYID/$repositoryId/g" $defaultPackageFile + # Test that URL is ok + wget -q --spider "$url" + if [[ $? -eq 0 ]]; then + echo "Ready to upload $pkgName [$pkgVer]" + else + echo "ERROR testing URL $url" + return + fi + # Perform Upload + AddPackage $defaultPackageFile + # Cleanup + # rm $defaultPackageFile +} + +# Upload multiple packages by reading urls line-by-line from the specified file +function AddPackages +{ + urlFile=$1 + if [ -z $urlFile ]; then + echo "Error: Must specify a flat text file containing one or more URLs" + exit 1 + fi + if [ ! -f $urlFile ]; then + echo "Error: Cannot add packages. File $urlFile does not exist" + exit 1 + fi + for url in $(cat $urlFile); do + AddPackageByUrl "$url" + sleep 5 + done +} + +# Delete the specified repo +function DeleteRepo +{ + repoId=$1 + if [ -z $repoId ]; then + echo "Error: Please specify repository ID. Run -listrepos for a list of IDs" + exit 1 + fi + curl -I -k -X DELETE "$baseurl/v1/repositories/$repoId" + BailIf $? +} + +# Delete the specified package +function DeletePackage +{ + packageId=$1 + if [ -z $packageId ]; then + echo "Error: Please specify package ID. Run -listpkgs for a list of IDs" + exit 1 + fi + echo Removing pkgId $packageId from repo $repositoryId + curl -I -k -X DELETE "$baseurl/v1/packages/$packageId" + BailIf $? +} + +if [[ "$1" == "-listrepos" ]]; then + echo "Fetching repo list from $server..." + curl -k "$baseurl/v1/repositories" | sed 's/,/,\n/g' | sed 's/^"/\t"/g' + echo "" +elif [[ "$1" == "-listpkgs" ]]; then + echo "Fetching package list from $server" + ListPackages $2 +elif [[ "$1" == "-addrepo" ]]; then + AddRepo $2 +elif [[ "$1" == "-addpkg" ]]; then + AddPackage $2 +elif [[ "$1" == "-addpkgs" ]]; then + AddPackages $2 +elif [[ "$1" == "-delrepo" ]]; then + DeleteRepo $2 +elif [[ "$1" == "-delpkg" ]]; then + DeletePackage $2 +else + echo "USAGE: ./repotool.sh -OPTION" + echo "-listrepos: Gather a list of repos" + echo "-listpkgs: Gather a list of packages" + echo "-addrepo [FILENAME] : Create a new repo using the specified JSON file" + echo "-addpkg [FILENAME] : Add package to repo using the specified JSON file" + echo "-addpkgs [FILENAME] : Add packages to repo using urls contained in FILENAME" + echo "-delrepo REPOID : Delete the specified repo by ID" + echo "-delpkg PKGID : Delete the specified package by ID" +fi diff --git a/src/Microsoft.Extensions.ProjectModel/ProjectContextBuilder.cs b/src/Microsoft.Extensions.ProjectModel/ProjectContextBuilder.cs index 42f18dd1d..a76609447 100644 --- a/src/Microsoft.Extensions.ProjectModel/ProjectContextBuilder.cs +++ b/src/Microsoft.Extensions.ProjectModel/ProjectContextBuilder.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.Extensions.Internal; using Microsoft.Extensions.ProjectModel.Graph; using Microsoft.Extensions.ProjectModel.Resolution; using NuGet.Frameworks; @@ -32,8 +33,10 @@ namespace Microsoft.Extensions.ProjectModel if (GlobalSettings == null) { + RootDirectory = ProjectRootResolver.ResolveRootDirectory(ProjectDirectory); + GlobalSettings globalSettings; - if (GlobalSettings.TryGetGlobalSettings(ProjectDirectory, out globalSettings)) + if (GlobalSettings.TryGetGlobalSettings(RootDirectory, out globalSettings)) { GlobalSettings = globalSettings; } @@ -63,13 +66,13 @@ namespace Microsoft.Extensions.ProjectModel lockFileLookup = new LockFileLookup(LockFile); } - var libraries = new Dictionary(); + var libraries = new Dictionary(); var projectResolver = new ProjectDependencyProvider(); var mainProject = projectResolver.GetDescription(TargetFramework, Project); // Add the main project - libraries.Add(mainProject.Identity.Name, mainProject); + libraries.Add(new LibraryKey(mainProject.Identity.Name), mainProject); LockFileTarget target = null; if (lockFileLookup != null) @@ -121,7 +124,7 @@ namespace Microsoft.Extensions.ProjectModel libraryManager); } - private void ResolveDependencies(Dictionary libraries, ReferenceAssemblyDependencyResolver referenceAssemblyDependencyResolver) + private void ResolveDependencies(Dictionary libraries, ReferenceAssemblyDependencyResolver referenceAssemblyDependencyResolver) { foreach (var library in libraries.Values.ToList()) { @@ -135,8 +138,11 @@ namespace Microsoft.Extensions.ProjectModel library.Framework = library.Framework ?? TargetFramework; foreach (var dependency in library.Dependencies) { + var keyType = dependency.Target == LibraryType.ReferenceAssembly ? LibraryType.ReferenceAssembly : LibraryType.Unspecified; + var key = new LibraryKey(dependency.Name, keyType); + LibraryDescription dep; - if (!libraries.TryGetValue(dependency.Name, out dep)) + if (!libraries.TryGetValue(key, out dep)) { if (Equals(LibraryType.ReferenceAssembly, dependency.Target)) { @@ -144,12 +150,12 @@ namespace Microsoft.Extensions.ProjectModel UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework); dep.Framework = TargetFramework; - libraries[dependency.Name] = dep; + libraries[key] = dep; } else { dep = UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework); - libraries[dependency.Name] = dep; + libraries[key] = dep; } } @@ -159,7 +165,7 @@ namespace Microsoft.Extensions.ProjectModel } } - private void ScanLibraries(LockFileTarget target, LockFileLookup lockFileLookup, Dictionary libraries, PackageDependencyProvider packageResolver, ProjectDependencyProvider projectResolver) + private void ScanLibraries(LockFileTarget target, LockFileLookup lockFileLookup, Dictionary libraries, PackageDependencyProvider packageResolver, ProjectDependencyProvider projectResolver) { foreach (var library in target.Libraries) { @@ -171,7 +177,7 @@ namespace Microsoft.Extensions.ProjectModel var projectDescription = projectResolver.GetDescription(library.Name, path, library); - libraries.Add(projectDescription.Identity.Name, projectDescription); + libraries.Add(new LibraryKey(projectDescription.Identity.Name), projectDescription); } else { @@ -179,7 +185,7 @@ namespace Microsoft.Extensions.ProjectModel var packageDescription = packageResolver.GetDescription(packageEntry, library); - libraries.Add(packageDescription.Identity.Name, packageDescription); + libraries.Add(new LibraryKey(packageDescription.Identity.Name), packageDescription); } } } @@ -223,5 +229,38 @@ namespace Microsoft.Extensions.ProjectModel return null; } + + private struct LibraryKey + { + public LibraryKey(string name) : this(name, LibraryType.Unspecified) + { + } + + public LibraryKey(string name, LibraryType libraryType) + { + Name = name; + LibraryType = libraryType; + } + + public string Name { get; } + public LibraryType LibraryType { get; } + + public override bool Equals(object obj) + { + var otherKey = (LibraryKey)obj; + + return string.Equals(otherKey.Name, Name, StringComparison.Ordinal) && + otherKey.LibraryType.Equals(LibraryType); + } + + public override int GetHashCode() + { + var combiner = new HashCodeCombiner(); + combiner.Add(Name); + combiner.Add(LibraryType); + + return combiner.CombinedHash; + } + } } }