diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 000000000000..dbf903ae14d4
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,16 @@
+# editorconfig.org
+
+# top-most EditorConfig file
+root = true
+
+# Default settings:
+# A newline ending every file
+# Use 4 spaces as indentation
+[*]
+insert_final_newline = true
+indent_style = space
+indent_size = 4
+
+# Trim trailing whitespace, limited support.
+# https://github.com/editorconfig/editorconfig/wiki/Property-research:-Trim-trailing-spaces
+trim_trailing_whitespace = true
\ No newline at end of file
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000000..a664be3a859b
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,49 @@
+*.doc diff=astextplain
+*.DOC diff=astextplain
+*.docx diff=astextplain
+*.DOCX diff=astextplain
+*.dot diff=astextplain
+*.DOT diff=astextplain
+*.pdf diff=astextplain
+*.PDF diff=astextplain
+*.rtf diff=astextplain
+*.RTF diff=astextplain
+
+*.jpg binary
+*.png binary
+*.gif binary
+
+*.cs text=auto diff=csharp
+*.vb text=auto
+*.c text=auto
+*.cpp text=auto
+*.cxx text=auto
+*.h text=auto
+*.hxx text=auto
+*.py text=auto
+*.rb text=auto
+*.java text=auto
+*.html text=auto
+*.htm text=auto
+*.css text=auto
+*.scss text=auto
+*.sass text=auto
+*.less text=auto
+*.js text=auto
+*.lisp text=auto
+*.clj text=auto
+*.sql text=auto
+*.php text=auto
+*.lua text=auto
+*.m text=auto
+*.asm text=auto
+*.erl text=auto
+*.fs text=auto
+*.fsx text=auto
+*.hs text=auto
+
+*.csproj text=auto merge=union
+*.vbproj text=auto merge=union
+*.fsproj text=auto merge=union
+*.dbproj text=auto merge=union
+*.sln text=auto eol=crlf merge=union
diff --git a/.gitignore b/.gitignore
index 16994e0ab195..1226db8c7149 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,13 +46,7 @@ src/Umbraco.Web.UI/Web.*.config.transformed
umbraco/presentation/umbraco/plugins/uComponents/uComponentsInstaller.ascx
umbraco/presentation/packages/uComponents/MultiNodePicker/CustomTreeService.asmx
-_BuildOutput/*
*.ncrunchsolution
-build/UmbracoCms.AllBinaries*zip
-build/UmbracoCms.WebPI*zip
-build/UmbracoCms*zip
-build/UmbracoExamine.PDF*zip
-build/*.nupkg
src/Umbraco.Tests/config/applications.config
src/Umbraco.Tests/config/trees.config
src/Umbraco.Web.UI/web.config
@@ -68,9 +62,9 @@ src/packages/repositories.config
src/Umbraco.Web.UI/[Ww]eb.config
*.transformed
-webpihash.txt
node_modules
+lib-bower
src/Umbraco.Web.UI/[Uu]mbraco/[Ll]ib/*
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/umbraco.*
@@ -95,7 +89,6 @@ src/Umbraco.Web.UI/[Uu]mbraco/[Aa]ssets/*
src/Umbraco.Web.UI.Client/[Bb]uild/*
src/Umbraco.Web.UI.Client/[Bb]uild/[Bb]elle/
src/Umbraco.Web.UI/[Uu]ser[Cc]ontrols/
-build/_BuildOutput/
src/Umbraco.Web.UI.Client/src/[Ll]ess/*.css
tools/NDepend/
@@ -120,6 +113,7 @@ build/ApiDocs/*
build/ApiDocs/Output/*
src/Umbraco.Web.UI.Client/bower_components/*
/src/Umbraco.Web.UI/Umbraco/preview
+/src/Umbraco.Web.UI/Umbraco/preview.old
#Ignore Rule for output of generated documentation files from Grunt docserve
src/Umbraco.Web.UI.Client/docs/api
@@ -130,7 +124,6 @@ src/*.boltdata/
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.config.js
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.front.js
src/umbraco.sln.ide/*
-build/UmbracoCms.*/
src/.vs/
src/Umbraco.Web.UI/umbraco/js/install.loader.js
src/Umbraco.Tests/media
@@ -140,5 +133,12 @@ apidocs/api/*
build/docs.zip
build/ui-docs.zip
build/csharp-docs.zip
-build/msbuild.log
.vs/
+src/packages/
+src/PrecompiledWeb/*
+
+
+build.out/
+build.tmp/
+build/Modules/*/temp/
+/src/.idea/*
diff --git a/BUILD.md b/BUILD.md
new file mode 100644
index 000000000000..b9c4e36d2090
--- /dev/null
+++ b/BUILD.md
@@ -0,0 +1,186 @@
+Umbraco Cms Build
+--
+----
+
+# Quick!
+
+To build Umbraco, fire PowerShell and move to Umbraco's repository root (the directory that contains `src`, `build`, `README.md`...). There, trigger the build with the following command:
+
+ build\build.ps1
+
+By default, this builds the current version. It is possible to specify a different version as a parameter to the build script:
+
+ build\build.ps1 7.6.44
+
+Valid version strings are defined in the `Set-UmbracoVersion` documentation below.
+
+## PowerShell Quirks
+
+There is a good chance that running `build.ps1` ends up in error, with messages such as
+
+>The file ...\build\build.ps1 is not digitally signed. You cannot run this script on the current system. For more information about running scripts and setting execution policy, see about_Execution_Policies.
+
+PowerShell has *Execution Policies* that may prevent the script from running. You can check the current policies with:
+
+ PS> Get-ExecutionPolicy -List
+
+ Scope ExecutionPolicy
+ ----- ---------------
+ MachinePolicy Undefined
+ UserPolicy Undefined
+ Process Undefined
+ CurrentUser Undefined
+ LocalMachine RemoteSigned
+
+Policies can be `Restricted`, `AllSigned`, `RemoteSigned`, `Unrestricted` and `Bypass`. Scopes can be `MachinePolicy`, `UserPolicy`, `Process`, `CurrentUser`, `LocalMachine`. You need the current policy to be `RemoteSigned`—as long as it is `Undefined`, the script cannot run. You can change the current user policy with:
+
+ PS> Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
+
+Alternatively, you can do it at machine level, from within an elevated PowerShell session:
+
+ PS> Set-ExecutionPolicy -Scope LocalMachine -ExecutionPolicy RemoteSigned
+
+And *then* the script should run. It *might* however still complain about executing scripts, with messages such as:
+
+>Security warning - Run only scripts that you trust. While scripts from the internet can be useful, this script can potentially harm your computer. If you trust this script, use the Unblock-File cmdlet to allow the script to run without this warning message. Do you want to run ...\build\build.ps1?
+[D] Do not run [R] Run once [S] Suspend [?] Help (default is "D"):
+
+This is usually caused by the scripts being *blocked*. And that usually happens when the source code has been downloaded as a Zip file. When Windows downloads Zip files, they are marked as *blocked* (technically, they have a Zone.Identifier alternate data stream, with a value of "3" to indicate that they were downloaded from the Internet). And when such a Zip file is un-zipped, each and every single file is also marked as blocked.
+
+The best solution is to unblock the Zip file before un-zipping: right-click the files, open *Properties*, and there should be a *Unblock* checkbox at the bottom of the dialog. If, however, the Zip file has already been un-zipped, it is possible to recursively unblock all files from PowerShell with:
+
+ PS> Get-ChildItem -Recurse *.* | Unblock-File
+
+## Notes
+
+Git might have issues dealing with long file paths during build. You may want/need to enable `core.longpaths` support (see [this page](https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path) for details).
+
+# Build
+
+The Umbraco Build solution relies on a PowerShell module. The module needs to be imported into PowerShell. From within Umbraco's repository root:
+
+ build\build.ps1 -ModuleOnly
+
+Or the abbreviated form:
+
+ build\build.ps1 -mo
+
+Once the module has been imported, a set of commands are added to PowerShell.
+
+## Get-UmbracoBuildEnv
+
+Gets the Umbraco build environment ie NuGet, Semver, Visual Studio, etc. Downloads things that can be downloaded such as NuGet. Examples:
+
+ $uenv = Get-UmbracoBuildEnv
+ Write-Host $uenv.SolutionRoot
+ &$uenv.NuGet help
+
+The object exposes the following properties:
+
+* `SolutionRoot`: the absolute path to the solution root
+* `VisualStudio`: a Visual Studio object (see below)
+* `NuGet`: the absolute path to the NuGet executable
+* `Zip`: the absolute path to the 7Zip executable
+* `VsWhere`: the absolute path to the VsWhere executable
+* `NodePath`: the absolute path to the Node install
+* `NpmPath`: the absolute path to the Npm install
+
+The Visual Studio object is `null` when Visual Studio has not been detected (eg on VSTS). When not null, the object exposes the following properties:
+
+* `Path`: Visual Studio installation path (eg some place under `Program Files`)
+* `Major`: Visual Studio major version (eg `15` for VS 2017)
+* `Minor`: Visual Studio minor version
+* `MsBUild`: the absolute path to the MsBuild executable
+
+## Get-UmbracoVersion
+
+Gets an object representing the current Umbraco version. Example:
+
+ $v = Get-UmbracoVersion
+ Write-Host $v.Semver
+
+The object exposes the following properties:
+
+* `Semver`: the semver object representing the version
+* `Release`: the main part of the version (eg `7.6.33`)
+* `Comment`: the pre release part of the version (eg `alpha02`)
+* `Build`: the build number part of the version (eg `1234`)
+
+## Set-UmbracoVersion
+
+Modifies Umbraco files with the new version.
+
+>This entirely replaces the legacy `UmbracoVersion.txt` file.
+
+The version must be a valid semver version. It can include a *pre release* part (eg `alpha02`) and/or a *build number* (eg `1234`). Examples:
+
+ Set-UmbracoVersion 7.6.33
+ Set-UmbracoVersion 7.6.33-alpha02
+ Set-UmbracoVersion 7.6.33+1234
+ Set-UmbracoVersion 7.6.33-beta05+5678
+
+Note that `Set-UmbracoVersion` enforces a slightly more restrictive naming scheme than what semver would tolerate. The pre release part can only be composed of a-z and 0-9, therefore `alpha033` is considered valid but not `alpha.033` nor `alpha033-preview` nor `RC2` (would need to be lowercased `rc2`).
+
+>It is considered best to add trailing zeroes to pre releases, else NuGet gets the order of versions wrong. So if you plan to have more than 10, but no more that 100 alpha versions, number the versions `alpha00`, `alpha01`, etc.
+
+## Build-Umbraco
+
+Builds Umbraco. Temporary files are generated in `build.tmp` while the actual artifacts (zip files, NuGet packages...) are produced in `build.out`. Example:
+
+ Build-Umbraco
+
+Some log files, such as MsBuild logs, are produced in `build.tmp` too. The `build` directory should remain clean during a build.
+
+### web.config
+
+Building Umbraco requires a clean `web.config` file in the `Umbraco.Web.UI` project. If a `web.config` file already exists, the `pre-build` task (see below) will save it as `web.config.temp-build` and replace it with a clean copy of `web.Template.config`. The original file is replaced once it is safe to do so, by the `pre-packages` task.
+
+## Build-UmbracoDocs
+
+Builds umbraco documentation. Temporary files are generated in `build.tmp` while the actual artifacts (docs...) are produced in `build.out`. Example:
+
+ Build-UmbracoDocs
+
+Some log files, such as MsBuild logs, are produced in `build.tmp` too. The `build` directory should remain clean during a build.
+
+## Verify-NuGet
+
+Verifies that projects all require the same version of their dependencies, and that NuSpec files require versions that are consistent with projects. Example:
+
+ Verify-NuGet
+
+# VSTS
+
+Continuous integration, nightly builds and release builds run on VSTS.
+
+VSTS uses the `Build-Umbraco` command several times, each time passing a different *target* parameter. The supported targets are:
+
+* `pre-build`: prepares the build
+* `compile-belle`: compiles Belle
+* `compile-umbraco`: compiles Umbraco
+* `pre-tests`: prepares the tests
+* `compile-tests`: compiles the tests
+* `pre-packages`: prepares the packages
+* `pkg-zip`: creates the zip files
+* `pre-nuget`: prepares NuGet packages
+* `pkg-nuget`: creates NuGet packages
+
+All these targets are executed when `Build-Umbraco` is invoked without a parameter (or with the `all` parameter). On VSTS, compilations (of Umbraco and tests) are performed by dedicated VSTS tasks. Similarly, creating the NuGet packages is also performed by dedicated VSTS tasks.
+
+Finally, the produced artifacts are published in two containers that can be downloaded from VSTS: `zips` contains the zip files while `nuget` contains the NuGet packages.
+
+>During a VSTS build, some environment `UMBRACO_*` variables are exported by the `pre-build` target and can be reused in other targets *and* in VSTS tasks. The `UMBRACO_TMP` environment variable is used in `Umbraco.Tests` to disable some tests that have issues with VSTS at the moment.
+
+# Notes
+
+*This part needs to be cleaned up*
+
+Nightlies should use some sort of build number.
+
+We should increment versions as soon as a version is released. Ie, as soon as `7.6.33` is released, we should `Set-UmbracoVersion 7.6.34-alpha` and push.
+
+NuGet / NuSpec consistency checks are performed in tests. We should move it so it is done as part of the PowerShell script even before we try to compile and run the tests.
+
+There are still a few commands in `build` (to build docs, install Git or cleanup the install) that will need to be migrated to PowerShell.
+
+/eof
\ No newline at end of file
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000000..3baa5dbe66c4
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,80 @@
+# Code of Conduct
+
+## 1. Purpose
+
+A primary goal of Umbraco CMS is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof).
+
+This code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior.
+
+We invite all those who participate in Umbraco CMS to help us create safe and positive experiences for everyone.
+
+## 2. Open Source Citizenship
+
+A supplemental goal of this Code of Conduct is to increase open source citizenship by encouraging participants to recognize and strengthen the relationships between our actions and their effects on our community.
+
+Communities mirror the societies in which they exist and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society.
+
+If you see someone who is making an extra effort to ensure our community is welcoming, friendly, and encourages all participants to contribute to the fullest extent, we want to know.
+
+## 3. Expected Behavior
+
+The following behaviors are expected and requested of all community members:
+
+* Participate in an authentic and active way. In doing so, you contribute to the health and longevity of this community.
+* Exercise consideration and respect in your speech and actions.
+* Attempt collaboration before conflict.
+* Refrain from demeaning, discriminatory, or harassing behavior and speech.
+* Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential.
+* Remember that community event venues may be shared with members of the public; please be respectful to all patrons of these locations.
+
+## 4. Unacceptable Behavior
+
+The following behaviors are considered harassment and are unacceptable within our community:
+
+* Violence, threats of violence or violent language directed against another person.
+* Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language.
+* Posting or displaying sexually explicit or violent material.
+* Posting or threatening to post other people’s personally identifying information ("doxing").
+* Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability.
+* Inappropriate photography or recording.
+* Inappropriate physical contact. You should have someone’s consent before touching them.
+* Unwelcome sexual attention. This includes, sexualized comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances.
+* Deliberate intimidation, stalking or following (online or in person).
+* Advocating for, or encouraging, any of the above behavior.
+* Sustained disruption of community events, including talks and presentations.
+
+## 5. Consequences of Unacceptable Behavior
+
+Unacceptable behavior from any community member, including sponsors and those with decision-making authority, will not be tolerated.
+
+Anyone asked to stop unacceptable behavior is expected to comply immediately.
+
+If a community member engages in unacceptable behavior, the community organizers may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community without warning (and without refund in the case of a paid event).
+
+## 6. Reporting Guidelines
+
+If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible. Please contact Sebastiaan Janssen - [sj@umbraco.dk](mailto:sj@umbraco.dk).
+
+Additionally, community organizers are available to help community members engage with local law enforcement or to otherwise help those experiencing unacceptable behavior feel safe. In the context of in-person events, organizers will also provide escorts as desired by the person experiencing distress.
+
+## 7. Addressing Grievances
+
+If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify Umbraco with a concise description of your grievance. Your grievance will be handled in accordance with our existing governing policies.
+
+## 8. Scope
+
+We expect all community participants (contributors, paid or otherwise; sponsors; and other guests) to abide by this Code of Conduct in all community venues–online and in-person–as well as in all one-on-one communications pertaining to community business.
+
+This code of conduct and its related procedures also applies to unacceptable behavior occurring outside the scope of community activities when such behavior has the potential to adversely affect the safety and well-being of community members.
+
+## 9. Contact info
+
+Sebastiaan Janssen - [sj@umbraco.dk](mailto:sj@umbraco.dk)
+
+## 10. License and attribution
+
+This Code of Conduct is distributed under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/).
+
+Portions of text derived from the [Django Code of Conduct](https://www.djangoproject.com/conduct/) and the [Geek Feminism Anti-Harassment Policy](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy).
+
+Retrieved on November 22, 2016 from [http://citizencodeofconduct.org/](http://citizencodeofconduct.org/)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000000..f8d8aac34288
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,207 @@
+# Contributing to Umbraco CMS
+
+👍🎉 First off, thanks for taking the time to contribute! 🎉👍
+
+The following is a set of guidelines for contributing to Umbraco CMS.
+
+These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
+
+Remember, we're a friendly bunch and are happy with whatever contribution you might provide. Below are guidelines for success that we've gathered over the years. If you choose to ignore them then we still love you 💖.
+
+#### Table Of Contents
+
+[Code of Conduct](#code-of-conduct)
+
+[How Can I Contribute?](#how-can-i-contribute)
+ * [Reporting Bugs](#reporting-bugs)
+ * [Suggesting Enhancements](#suggesting-enhancements)
+ * [Your First Code Contribution](#your-first-code-contribution)
+ * [Pull Requests](#pull-requests)
+
+[Styleguides](#styleguides)
+
+[What should I know before I get started?](#what-should-i-know-before-i-get-started)
+ * [Working with the source code](#working-with-the-source-code)
+ * [What branch should I target for my contributions?](#what-branch-should-i-target-for-my-contributions)
+ * [Building Umbraco from source code](#building-umbraco-from-source-code)
+ * [Keeping your Umbraco fork in sync with the main repository](#keeping-your-umbraco-fork-in-sync-with-the-main-repository)
+
+[How do I even begin?](#how-do-i-even-begin)
+
+[Problems?](#problems)
+
+[Credits](#credits)
+
+## Code of Conduct
+
+This project and everyone participating in it is governed by the [our Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [Sebastiaan Janssen - sj@umbraco.dk](mailto:sj@umbraco.dk).
+
+## How Can I Contribute?
+
+### Reporting Bugs
+This section guides you through submitting a bug report for Umbraco CMS. Following these guidelines helps maintainers and the community understand your report 📝, reproduce the behavior 💻 💻, and find related reports 🔎.
+
+Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](http://issues.umbraco.org/issues#newissue=61-30118), the information it asks for helps us resolve issues faster.
+
+> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one.
+
+##### Before Submitting A Bug Report
+
+ * Most importantly, check **if you can reproduce the problem** in the [latest version of Umbraco](https://our.umbraco.org/download/). We might have already fixed your particular problem.
+ * It also helps tremendously to check if the issue you're experiencing is present in **a clean install** of the Umbraco version you're currently using. Custom code can have side-effects that don't occur in a clean install.
+ * **Use the Google**. Whatever you're experiencing, Google it plus "Umbraco" - usually you can get some pretty good hints from the search results, including open issues and further troubleshooting hints.
+ * If you do find and existing issue has **and the issue is still open**, add a comment to the existing issue if you have additional information. If you have the same problem and no new info to add, just "star" the issue.
+
+Explain the problem and include additional details to help maintainers reproduce the problem. The following is a long description which we've boiled down into a few very simple question in the issue tracker when you create a new issue. We're listing the following hints to indicate that the most successful reports usually have a lot of this ground covered:
+
+ * **Use a clear and descriptive title** for the issue to identify the problem.
+ * **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining which steps you took in the backoffice to get to a certain undesireable result, e.g. you created a document type, inherting 3 levels deep, added a certain datatype, tried to save it and you got an error.
+ * **Provide specific examples to demonstrate the steps**. If you wrote some code, try to provide a code sample as specific as possible to be able to reproduce the behavior.
+ * **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
+ * **Explain which behavior you expected to see instead and why.**
+
+Provide more context by answering these questions:
+
+ * **Can you reproduce the problem** when `debug="false"` in your `web.config` file?
+ * **Did the problem start happening recently** (e.g. after updating to a new version of Umbraco) or was this always a problem?
+ * **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens.
+
+Include details about your configuration and environment:
+
+ * **Which version of Umbraco are you using?**
+ * **What is the environment you're using Umbraco in?** Is this a problem on your local machine or on a server. Tell us about your configuration: Windows version, IIS/IISExpress, database type, etc.
+ * **Which packages do you have installed?**
+
+### Suggesting Enhancements
+
+This section guides you through submitting an enhancement suggestion for Atom, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion 📝 and find related suggestions 🔎.
+
+Most of the suggestions in the [reporting bugs](#reporting-bugs) section also count for suggesting enhancements.
+
+Some additional hints that may be helpful:
+
+ * **Include screenshots and animated GIFs** which help you demonstrate the steps or point out the part of Umbraco which the suggestion is related to.
+ * **Explain why this enhancement would be useful to most Umbraco users** and isn't something that can or should be implemented as a [community package](https://our.umbraco.org/projects/).
+
+### Your First Code Contribution
+
+Unsure where to begin contributing to Umbraco? You can start by looking through [these `Up for grabs` and issues](http://issues.umbraco.org/issues/U4?q=%28project%3A+%7BU4%7D+Difficulty%3A+%7BVery+Easy%7D+%23Easy+%23Unresolved+Priority%3A+Normal+%23Major+%23Show-stopper+State%3A+-%7BIn+Progress%7D+sort+by%3A+votes+Affected+versions%3A+-6.*+Affected+versions%3A+-4.*%29+OR+%28tag%3A+%7BUp+For+Grabs%7D+%23Unresolved+%29).
+
+The issue list is sorted by total number of upvotes. While not perfect, number of upvotes is a reasonable proxy for impact a given change will have.
+
+### Pull Requests
+
+The most successful pull requests usually look a like this:
+
+ * Fill in the required template
+ * Include screenshots and animated GIFs in your pull request whenever possible.
+ * Unit tests, while optional are awesome, thank you!
+ * New code is commented with documentation from which [the reference documentation](https://our.umbraco.org/documentation/Reference/) is generated
+
+Again, these are guidelines, not strict requirements.
+
+## Styleguides
+
+To be honest, we don't like rules very much. We trust you have the best of intentions and we encourage you to create working code. If it doesn't look perfect then we'll happily help clean it up.
+
+That said, the Umbraco development team likes to follow the hints that ReSharper gives us (no problem if you don't have this installed) and we've added a `.editorconfig` file so that Visual Studio knows what to do with whitespace, line endings, etc.
+
+## What should I know before I get started?
+
+### Working with the source code
+
+Some parts of our source code is over 10 years old now. And when we say "old", we mean "mature" of course!
+
+There's two big areas that you should know about:
+
+ 1. The Umbraco backoffice is a extensible AngularJS app and requires you to run a `gulp dev` command while you're working with it, so changes are copied over to the appropriate directories and you can refresh your browser to view the results of your changes.
+ You may need to run the following commands to set up gulp properly:
+ ```
+ npm cache clean
+ npm install -g bower
+ npm install -g gulp
+ npm install -g gulp-cli
+ npm install
+ gulp build
+ ```
+ 2. "The rest" is a C# based codebase, with some traces of our WebForms past but mostly ASP.NET MVC based these days. You can make changes, build them in Visual Studio, and hit `F5` to see the result.
+
+To find the general areas of something you're looking to fix or improve, have a look at the following two parts of the API documentation.
+
+ * [The AngularJS based backoffice files](https://our.umbraco.org/apidocs/ui/#/api) (to be found in `src\Umbraco.Web.UI.Client\src`)
+ * [The rest](https://our.umbraco.org/apidocs/csharp/)
+
+### What branch should I target for my contributions?
+
+We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-flow/), don't worry if you are not familiar with it. The most important thing you need to know is that when you fork the Umbraco repository, the default branch is set to something, usually `dev-v7`. Whatever the default is, that's where we'd like you to target your contributions.
+
+![What branch do you want me to target?](tools/contributing/defaultbranch.png)
+
+### Building Umbraco from source code
+
+The easiest way to get started is to run `build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `gulp dev` in `src\Umbraco.Web.UI.Client`. See [this page](BUILD.md) for more details.
+
+Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 ([the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
+
+![Gulp build in Visual Studio](tools/contributing/gulpbuild.png)
+
+After this build completes, you should be able to hit `F5` in Visual Studio to build and run the project. A IISExpress webserver will start and the Umbraco installer will pop up in your browser, follow the directions there to get a working Umbraco install up and running.
+
+### Keeping your Umbraco fork in sync with the main repository
+
+We recommend you sync with our repository before you submit your pull request. That way, you can fix any potential merge conflicts and make our lives a little bit easier.
+
+Also, if you've submitted a pull request three weeks ago and want to work on something new, you'll want to get the latest code to build against of course.
+
+To sync your fork with this original one, you'll have to add the upstream url, you only have to do this once:
+
+```
+git remote add upstream https://github.com/umbraco/Umbraco-CMS.git
+```
+
+Then when you want to get the changes from the main repository:
+
+```
+git fetch upstream
+git rebase upstream/dev-v7
+```
+
+In this command we're syncing with the `dev-v7` branch, but you can of course choose another one if needed.
+
+(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
+
+## How do I even begin?
+
+Great question! The short version goes like this:
+
+ * **Fork** - create a fork of [`Umbraco-CMS` on GitHub](https://github.com/umbraco/Umbraco-CMS)
+
+ ![Fork the repository](tools/contributing/forkrepository.png)
+
+ * **Clone** - when GitHub has created your fork, you can clone it in your favorite Git tool
+
+ ![Clone the fork](tools/contributing/clonefork.png)
+
+ * **Build** - build your fork of Umbraco locally as described in [building Umbraco from source code](#building-umbraco-from-source-code)
+ * **Change** - make your changes, experiment, have fun, explore and learn, and don't be afraid. We welcome all contributions and will happily give feedback
+ * **Commit** - done? Yay! 🎉 It is recommended to create a new branch now and name it after the issue you're fixing, we usually follow the format: `temp-U4-12345`. This means it's a temporary branch for the particular issue you're working on, in this case `U4-12345`
+ * **Push** - great, now you can push the changes up to your fork on GitHub
+ * **Create pull request** - exciting! You're ready to show us your changes (or not quite ready, you just need some feedback to progress). GitHub has picked up on the new branch you've pushed and will offer to create a Pull Request. Click that green button and away you go.
+
+ ![Create a pull request](tools/contributing/createpullrequest.png)
+
+The Umbraco development team can now start reviewing your proposed changes and give you feedback on them. If it's not perfect, we'll either fix up what we need or we can request you to make some additional changes.
+
+If you make the corrections we ask for in the same branch and push them to your fork again, the pull request automatically updates with the additional commit(s) so we can review it again. If all is well, we'll merge the code and your commits are forever part of Umbraco!
+
+Not all changes are wanted so on occassion we might close a PR without merging it. We will give you feedback why we can't accept your changes at this and we'll be nice about it, thanking you for spending your valueable time.
+
+Remember, if an issue is in the `Up for grabs` list or you've asked for some feedback before you send us a PR, your PR will not be closed as unwanted.
+
+## Problems?
+
+Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.org/forum/contributing-to-umbraco-cms/) forum, the team monitors that one closely!
+
+## Credits
+
+This contribution guide borrows heavily from the excellent work on [the Atom contribution guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md). A big [#h5yr](http://h5yr.com/) to them!
diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 000000000000..db1e5c88bda2
--- /dev/null
+++ b/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,11 @@
+### Prerequisites
+
+- [ ] I have written a descriptive pull-request title
+- [ ] I have linked this PR to an issue on the tracker at http://issues.umbraco.org
+
+### Description
+
+
+
+
+
diff --git a/README.md b/README.md
index 1d42543eb370..8aee632cadd1 100644
--- a/README.md
+++ b/README.md
@@ -1,51 +1,46 @@
+[![Build status](https://ci.appveyor.com/api/projects/status/6by6harxtxt0ocdx/branch/dev-v7?svg=true)](https://ci.appveyor.com/project/Umbraco/umbraco-cms-b2cri/branch/dev-v7)
+
Umbraco CMS
===========
-The friendliest, most flexible and fastest growing ASP.NET CMS used by more than 390,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
+The friendliest, most flexible and fastest growing ASP.NET CMS used by more than 443,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
[![ScreenShot](vimeo.png)](https://vimeo.com/172382998/)
-## Umbraco CMS ##
+## Umbraco CMS
Umbraco is a free open source Content Management System built on the ASP.NET platform. Our mission is to help you deliver delightful digital experiences by making Umbraco friendly, simpler and social.
-
-## Building Umbraco from source ##
-
-The easiest way to get started is to run `build/build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `grunt vs` in `src\Umbraco.Web.UI.Client`.
-
-If you're interested in making changes to Belle without running Visual Studio make sure to read the [Belle ReadMe file](src/Umbraco.Web.UI.Client/README.md).
-
-Note that you can always [download a nightly build](http://nightly.umbraco.org/?container=umbraco-750) so you don't have to build the code yourself.
-
-## Watch an introduction video ##
+## Watch an introduction video
[![ScreenShot](http://umbraco.com/images/whatisumbraco.png)](https://umbraco.tv/videos/umbraco-v7/content-editor/basics/introduction/cms-explanation/)
-## Umbraco - The Friendly CMS ##
+## Umbraco - The Friendly CMS
For the first time on the Microsoft platform, there is a free user and developer friendly CMS that makes it quick and easy to create websites - or a breeze to build complex web applications. Umbraco has award-winning integration capabilities and supports ASP.NET MVC or Web Forms, including User and Custom Controls, out of the box.
Umbraco is not only loved by developers, but is a content editors dream. Enjoy intuitive editing tools, media management, responsive views and approval workflows to send your content live.
-Used by more than 350,000 active websites including Carlsberg, Segway, Amazon and Heinz and **The Official ASP.NET and IIS.NET website from Microsoft** ([https://asp.net](https://asp.net) / [https://iis.net](https://iis.net)), you can be sure that the technology is proven, stable and scales. Backed by the team at Umbraco HQ, and supported by a dedicated community of over 200,000 craftspeople globally, you can trust that Umbraco is a safe choice and is here to stay.
+Used by more than 443,000 active websites including Carlsberg, Segway, Amazon and Heinz and **The Official ASP.NET and IIS.NET website from Microsoft** ([https://asp.net](https://asp.net) / [https://iis.net](https://iis.net)), you can be sure that the technology is proven, stable and scales. Backed by the team at Umbraco HQ, and supported by a dedicated community of over 220,000 craftspeople globally, you can trust that Umbraco is a safe choice and is here to stay.
To view more examples, please visit [https://umbraco.com/why-umbraco/#caseStudies](https://umbraco.com/why-umbraco/#caseStudies)
-## Why Open Source? ##
+## Why Open Source?
As an Open Source platform, Umbraco is more than just a CMS. We are transparent with our roadmap for future versions, our incremental sprint planning notes are publicly accessible and community contributions and packages are available for all to use.
-## Downloading ##
+## Trying out Umbraco CMS
+
+[Umbraco Cloud](https://umbraco.com) is the easiest and fastest way to use Umbraco yet with full support for all your custom .NET code and intergrations. You're up and running in less than a minute and your life will be made easier with automated upgrades and a built-in deployment engine. We offer a free 14 day trial, no credit card needed.
-The downloadable Umbraco releases live at [https://our.umbraco.org/download](https://our.umbraco.org/download).
+If you want to DIY you can [download Umbraco](https://our.umbraco.org/download) either as a ZIP file or via NuGet. It's the same version of Umbraco CMS that powers Umbraco Cloud, but you'll need to find a place to host yourself and handling deployments and upgrades is all down to you.
-## Forums ##
+## Community
-Peer-to-peer support is available 24/7 at the community forum on [https://our.umbraco.org](https://our.umbraco.org).
+Our friendly community is available 24/7 at the community hub we call ["Our Umbraco"](https://our.umbraco.org). Our Umbraco feature forums for questions and answers, documentation, downloadable plugins for Umbraco and a rich collection of community resources.
-## Contribute to Umbraco ##
+## Contribute to Umbraco
-Umbraco is contribution focused and community driven. If you want to contribute back to Umbraco please check out our [guide to contributing](https://our.umbraco.org/contribute).
+Umbraco is contribution focused and community driven. If you want to contribute back to Umbraco please check out our [guide to contributing](CONTRIBUTING.md).
-## Found a bug? ##
+## Found a bug?
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](https://our.umbraco.org/contribute/report-an-issue-or-request-a-feature).
diff --git a/appveyor.yml b/appveyor.yml
index 304444473001..4c9a33fd2310 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -1,22 +1,28 @@
version: '{build}'
shallow_clone: true
+
+init:
+ - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
+
build_script:
- cmd: >-
- cd build
-
- SET "release="
+ SET SLN=%CD%
- FOR /F "skip=1 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED release SET "release=%%i"
+ SET SRC=%SLN%\src
- SET nuGetFolder=C:\Users\appveyor\.nuget\packages
+ SET PACKAGES=%SRC%\packages
- ..\src\.nuget\NuGet.exe sources Add -Name MyGetUmbracoCore -Source https://www.myget.org/F/umbracocore/api/v2/ >NUL
+ CD build
- ..\src\.nuget\NuGet.exe install ..\src\Umbraco.Web.UI\packages.config -OutputDirectory %nuGetFolder% -Verbosity quiet
+ SET "release="
- IF EXIST ..\src\umbraco.businesslogic\packages.config ..\src\.nuget\NuGet.exe install ..\src\umbraco.businesslogic\packages.config -OutputDirectory %nuGetFolder% -Verbosity quiet
+ FOR /F "skip=1 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED release SET "release=%%i"
- ..\src\.nuget\NuGet.exe install ..\src\Umbraco.Core\packages.config -OutputDirectory %nuGetFolder% -Verbosity quiet
+ ECHO "Restoring NuGet into %PACKAGES%"
+
+ %SRC%\.nuget\NuGet.exe sources Add -Name MyGetUmbracoCore -Source https://www.myget.org/F/umbracocore/api/v2/ >NUL
+
+ %SRC%\.nuget\NuGet.exe restore %SRC%\umbraco.sln -Verbosity Quiet -NonInteractive -PackagesDirectory %PACKAGES%
ECHO Building Release %release% build%APPVEYOR_BUILD_NUMBER%
@@ -24,13 +30,12 @@ build_script:
SET MSBUILD="C:\Program Files (x86)\MSBuild\14.0\Bin\MsBuild.exe"
- XCOPY "..\src\Umbraco.Tests\unit-test-log4net.CI.config" "..\src\Umbraco.Tests\unit-test-log4net.config" /Y
+ XCOPY "%SRC%\Umbraco.Tests\unit-test-log4net.CI.config" "%SRC%\Umbraco.Tests\unit-test-log4net.config" /Y
- %MSBUILD% "..\src\Umbraco.Tests\Umbraco.Tests.csproj" /consoleloggerparameters:Summary;ErrorsOnly
+ %MSBUILD% "%SLN%/src/Umbraco.Tests/Umbraco.Tests.csproj" /consoleloggerparameters:Summary;ErrorsOnly;WarningsOnly /p:NugetPackagesDirectory=%PACKAGES%
- build.bat nopause %release% build%APPVEYOR_BUILD_NUMBER%
+ build.bat -integration -release:%release% -comment:build%APPVEYOR_BUILD_NUMBER% -nugetfolder:%PACKAGES%
- ECHO %PATH%
test:
assemblies: src\Umbraco.Tests\bin\Debug\Umbraco.Tests.dll
artifacts:
diff --git a/build.bat b/build.bat
new file mode 100644
index 000000000000..29a5e07a5a68
--- /dev/null
+++ b/build.bat
@@ -0,0 +1,14 @@
+@ECHO OFF
+powershell .\build\build.ps1
+
+IF ERRORLEVEL 1 (
+ GOTO :error
+) ELSE (
+ GOTO :EOF
+)
+
+:error
+ECHO.
+ECHO Can not run build\build.ps1.
+ECHO If this is due to a SecurityError then please refer to BUILD.md for help!
+ECHO.
diff --git a/build/Build.bat b/build/Build.bat
deleted file mode 100644
index fc0d8a69ea76..000000000000
--- a/build/Build.bat
+++ /dev/null
@@ -1,95 +0,0 @@
-@ECHO OFF
-IF NOT EXIST UmbracoVersion.txt (
- ECHO UmbracoVersion.txt missing!
- GOTO :showerror
-)
-
-REM Get the version and comment from UmbracoVersion.txt lines 2 and 3
-SET "release="
-SET "comment="
-FOR /F "skip=1 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED release SET "release=%%i"
-FOR /F "skip=2 delims=" %%i IN (UmbracoVersion.txt) DO IF NOT DEFINED comment SET "comment=%%i"
-
-REM If there's arguments on the command line overrule UmbracoVersion.txt and use that as the version
-IF [%2] NEQ [] (SET release=%2)
-IF [%3] NEQ [] (SET comment=%3) ELSE (IF [%2] NEQ [] (SET "comment="))
-
-REM Get the "is continuous integration" from the parameters
-SET "isci=0"
-IF [%1] NEQ [] (SET isci=1)
-
-SET version=%release%
-IF [%comment%] EQU [] (SET version=%release%) ELSE (SET version=%release%-%comment%)
-
-ECHO.
-ECHO Building Umbraco %version%
-ECHO.
-
-ReplaceIISExpressPortNumber.exe ..\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj %release%
-
-ECHO.
-ECHO Removing the belle build folder and bower_components folder to make sure everything is clean as a whistle
-RD ..\src\Umbraco.Web.UI.Client\build /Q /S
-RD ..\src\Umbraco.Web.UI.Client\bower_components /Q /S
-
-ECHO.
-ECHO Removing existing built files to make sure everything is clean as a whistle
-RMDIR /Q /S _BuildOutput
-DEL /F /Q UmbracoCms.*.zip
-DEL /F /Q UmbracoExamine.*.zip
-DEL /F /Q UmbracoCms.*.nupkg
-DEL /F /Q webpihash.txt
-
-ECHO.
-ECHO Making sure Git is in the path so that the build can succeed
-CALL InstallGit.cmd
-
-REM Adding the default Git path so that if it's installed it can actually be found
-REM This is necessary because SETLOCAL is on in InstallGit.cmd so that one might find Git,
-REM but the path setting is lost due to SETLOCAL
-path=C:\Program Files (x86)\Git\cmd;C:\Program Files\Git\cmd;%PATH%
-
-ECHO.
-ECHO Making sure we have a web.config
-IF NOT EXIST %CD%\..\src\Umbraco.Web.UI\web.config COPY %CD%\..\src\Umbraco.Web.UI\web.Template.config %CD%\..\src\Umbraco.Web.UI\web.config
-
-ECHO.
-ECHO.
-ECHO Performing MSBuild and producing Umbraco binaries zip files
-ECHO This takes a few minutes and logging is set to report warnings
-ECHO and errors only so it might seems like nothing is happening for a while.
-ECHO You can check the msbuild.log file for progress.
-ECHO.
-%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj" /p:BUILD_RELEASE=%release% /p:BUILD_COMMENT=%comment% /p:NugetPackagesDirectory=%nuGetFolder% /consoleloggerparameters:Summary;ErrorsOnly;WarningsOnly /fileLogger
-IF ERRORLEVEL 1 GOTO :error
-
-ECHO.
-ECHO Setting node_modules folder to hidden to prevent VS13 from crashing on it while loading the websites project
-attrib +h ..\src\Umbraco.Web.UI.Client\node_modules
-
-ECHO.
-ECHO Adding Web.config transform files to the NuGet package
-REN .\_BuildOutput\WebApp\Views\Web.config Web.config.transform
-REN .\_BuildOutput\WebApp\Xslt\Web.config Web.config.transform
-
-ECHO.
-ECHO Packing the NuGet release files
-..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.Core.nuspec -Version %version% -Symbols -Verbosity quiet
-..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.nuspec -Version %version% -Verbosity quiet
-IF ERRORLEVEL 1 GOTO :error
-
-:success
-ECHO.
-ECHO No errors were detected!
-ECHO There may still be some in the output, which you would need to investigate.
-ECHO Warnings are usually normal.
-GOTO :EOF
-
-:error
-
-ECHO.
-ECHO Errors were detected!
-
-REM don't pause if continuous integration else the build server waits forever
-REM before cancelling the build (and, there is noone to read the output anyways)
-IF isci NEQ 1 PAUSE
diff --git a/build/Build.proj b/build/Build.proj
deleted file mode 100644
index 9413b49d1562..000000000000
--- a/build/Build.proj
+++ /dev/null
@@ -1,347 +0,0 @@
-
-
-
-
-
- ..\MSBuildCommunityTasks
- ..\UmbracoMSBuildTasks
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- b.ToString("x2"))));
- }
- }
- }
- }
- }
- ]]>
-
-
-
-
-
-
-
-
-
- .$(BUILD_NUMBER)
-
-
- .$(BUILD_RELEASE)
-
-
- .$(BUILD_RELEASE)-$(BUILD_COMMENT)
-
-
- .$(BUILD_RELEASE)-$(BUILD_NIGHTLY)
-
-
- .$(BUILD_RELEASE)-$(BUILD_COMMENT)-$(BUILD_NIGHTLY)
-
-
-
- Release
- _BuildOutput\
- UmbracoCms$(DECIMAL_BUILD_NUMBER).zip
- UmbracoCms.AllBinaries$(DECIMAL_BUILD_NUMBER).zip
- UmbracoCms.WebPI$(DECIMAL_BUILD_NUMBER).zip
- False
- ..\..\build\$(BuildFolder)
- $(MSBuildProjectDirectory)\$(BuildFolder)
- $(BuildFolder)bin\
- $(BuildFolder)WebApp\
- $(BuildFolder)WebPi\
- $(BuildFolder)Configs\
- $(BuildFolderRelativeToProjects)bin\
- $(BuildFolderAbsolutePath)bin\
- $(BuildFolderRelativeToProjects)WebApp\
- $(BuildFolderAbsolutePath)WebApp\
- $(BuildFolderRelativeToProjects)WebPi\
- $(BuildFolderAbsolutePath)WebPi\
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(BUILD_RELEASE)
- $(BUILD_RELEASE)-$(BUILD_COMMENT)
- $(BUILD_RELEASE)-$(BUILD_NIGHTLY)
- $(BUILD_RELEASE)-$(BUILD_COMMENT)-$(BUILD_NIGHTLY)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/build/BuildBelle.bat b/build/BuildBelle.bat
deleted file mode 100644
index 8a07ee380a26..000000000000
--- a/build/BuildBelle.bat
+++ /dev/null
@@ -1,33 +0,0 @@
-@ECHO OFF
-SETLOCAL
-
-SET release=%1
-ECHO Installing Npm NuGet Package
-
-SET nuGetFolder=%CD%\..\src\packages\
-ECHO Configured packages folder: %nuGetFolder%
-ECHO Current folder: %CD%
-
-%CD%\..\src\.nuget\NuGet.exe install Npm.js -OutputDirectory %nuGetFolder% -Verbosity quiet
-
-for /f "delims=" %%A in ('dir %nuGetFolder%node.js.* /b') do set "nodePath=%nuGetFolder%%%A\"
-for /f "delims=" %%A in ('dir %nuGetFolder%npm.js.* /b') do set "npmPath=%nuGetFolder%%%A\tools\"
-
-ECHO Adding Npm and Node to path
-REM SETLOCAL is on, so changes to the path not persist to the actual user's path
-PATH=%npmPath%;%nodePath%;%PATH%
-
-SET buildFolder=%CD%
-
-ECHO Change directory to %CD%\..\src\Umbraco.Web.UI.Client\
-CD %CD%\..\src\Umbraco.Web.UI.Client\
-
-ECHO Do npm install and the grunt build of Belle
-call npm cache clean --quiet
-call npm install --quiet
-call npm install -g grunt-cli --quiet
-call npm install -g bower --quiet
-call grunt build --buildversion=%release%
-
-ECHO Move back to the build folder
-CD %buildFolder%
\ No newline at end of file
diff --git a/build/BuildDocs.bat b/build/BuildDocs.bat
deleted file mode 100644
index 9d0a04e1cd29..000000000000
--- a/build/BuildDocs.bat
+++ /dev/null
@@ -1,20 +0,0 @@
-@ECHO OFF
-SETLOCAL
-
-SET release=%1
-ECHO Installing Npm NuGet Package
-
-SET nuGetFolder=%CD%\..\src\packages\
-ECHO Configured packages folder: %nuGetFolder%
-ECHO Current folder: %CD%
-
-%CD%\..\src\.nuget\NuGet.exe install Npm.js -OutputDirectory %nuGetFolder% -Verbosity quiet
-
-for /f "delims=" %%A in ('dir %nuGetFolder%node.js.* /b') do set "nodePath=%nuGetFolder%%%A\"
-for /f "delims=" %%A in ('dir %nuGetFolder%npm.js.* /b') do set "npmPath=%nuGetFolder%%%A\tools\"
-
-ECHO Adding Npm and Node to path
-REM SETLOCAL is on, so changes to the path not persist to the actual user's path
-PATH=%npmPath%;%nodePath%;%PATH%
-
-Powershell.exe -ExecutionPolicy Unrestricted -File .\BuildDocs.ps1
\ No newline at end of file
diff --git a/build/BuildDocs.ps1 b/build/BuildDocs.ps1
deleted file mode 100644
index dcb3a85cc107..000000000000
--- a/build/BuildDocs.ps1
+++ /dev/null
@@ -1,100 +0,0 @@
-$PSScriptFilePath = (Get-Item $MyInvocation.MyCommand.Path);
-$RepoRoot = (get-item $PSScriptFilePath).Directory.Parent.FullName;
-$SolutionRoot = Join-Path -Path $RepoRoot "src";
-$ToolsRoot = Join-Path -Path $RepoRoot "tools";
-$DocFx = Join-Path -Path $ToolsRoot "docfx\docfx.exe"
-$DocFxFolder = (Join-Path -Path $ToolsRoot "docfx")
-$DocFxJson = Join-Path -Path $RepoRoot "apidocs\docfx.json"
-$7Zip = Join-Path -Path $ToolsRoot "7zip\7za.exe"
-$DocFxSiteOutput = Join-Path -Path $RepoRoot "apidocs\_site\*.*"
-$NgDocsSiteOutput = Join-Path -Path $RepoRoot "src\Umbraco.Web.UI.Client\docs\api\*.*"
-$ProgFiles86 = [Environment]::GetEnvironmentVariable("ProgramFiles(x86)");
-$MSBuild = "$ProgFiles86\MSBuild\14.0\Bin\MSBuild.exe"
-
-
-################ Do the UI docs
-
-"Changing to Umbraco.Web.UI.Client folder"
-cd ..
-cd src\Umbraco.Web.UI.Client
-Write-Host $(Get-Location)
-
-"Creating build folder so MSBuild doesn't run the whole grunt build"
-if (-Not (Test-Path "build")) {
- md "build"
-}
-
-"Installing node"
-# Check if Install-Product exists, should only exist on the build server
-if (Get-Command Install-Product -errorAction SilentlyContinue)
-{
- Install-Product node ''
-}
-
-"Installing node modules"
-& npm install
-
-"Installing grunt"
-& npm install -g grunt-cli
-
-"Moving back to build folder"
-cd ..
-cd ..
-cd build
-Write-Host $(Get-Location)
-
- & grunt --gruntfile ../src/umbraco.web.ui.client/gruntfile.js docs
-
-# change baseUrl
-$BaseUrl = "https://our.umbraco.org/apidocs/ui/"
-$IndexPath = "../src/umbraco.web.ui.client/docs/api/index.html"
-(Get-Content $IndexPath).replace('location.href.replace(rUrl, indexFile)', "`'" + $BaseUrl + "`'") | Set-Content $IndexPath
-# zip it
-
-& $7Zip a -tzip ui-docs.zip $NgDocsSiteOutput -r
-
-################ Do the c# docs
-
-# Build the solution in debug mode
-$SolutionPath = Join-Path -Path $SolutionRoot -ChildPath "umbraco.sln"
-& $MSBuild "$SolutionPath" /p:Configuration=Debug /maxcpucount /t:Clean
-if (-not $?)
-{
- throw "The MSBuild process returned an error code."
-}
-& $MSBuild "$SolutionPath" /p:Configuration=Debug /maxcpucount
-if (-not $?)
-{
- throw "The MSBuild process returned an error code."
-}
-
-# Go get docfx if we don't hae it
-$FileExists = Test-Path $DocFx
-If ($FileExists -eq $False) {
-
- If(!(Test-Path $DocFxFolder))
- {
- New-Item $DocFxFolder -type directory
- }
-
- $DocFxZip = Join-Path -Path $ToolsRoot "docfx\docfx.zip"
- $DocFxSource = "https://github.com/dotnet/docfx/releases/download/v1.9.4/docfx.zip"
- Invoke-WebRequest $DocFxSource -OutFile $DocFxZip
-
- #unzip it
- & $7Zip e $DocFxZip "-o$DocFxFolder"
-}
-
-#clear site
-If(Test-Path(Join-Path -Path $RepoRoot "apidocs\_site"))
-{
- Remove-Item $DocFxSiteOutput -recurse
-}
-
-# run it!
-& $DocFx metadata $DocFxJson
-& $DocFx build $DocFxJson
-
-# zip it
-
-& $7Zip a -tzip csharp-docs.zip $DocFxSiteOutput -r
diff --git a/build/InstallGit.cmd b/build/InstallGit.cmd
index e009e2594e1b..4daa2f45d91c 100644
--- a/build/InstallGit.cmd
+++ b/build/InstallGit.cmd
@@ -1,18 +1,18 @@
@ECHO OFF
SETLOCAL
- :: SETLOCAL is on, so changes to the path not persist to the actual user's path
+REM SETLOCAL is on, so changes to the path not persist to the actual user's path
git.exe --version
IF %ERRORLEVEL%==9009 GOTO :trydefaultpath
+REM OK, DONE
GOTO :EOF
- :: Git is installed, no need to to anything else
:trydefaultpath
PATH=C:\Program Files (x86)\Git\cmd;C:\Program Files\Git\cmd;%PATH%
git.exe --version
IF %ERRORLEVEL%==9009 GOTO :showerror
+REM OK, DONE
GOTO :EOF
- :: Git is installed, no need to to anything else
:showerror
ECHO Git is not in your path and could not be found in C:\Program Files (x86)\Git\cmd nor in C:\Program Files\Git\cmd
diff --git a/build/Modules/Umbraco.Build/Build-UmbracoDocs.ps1 b/build/Modules/Umbraco.Build/Build-UmbracoDocs.ps1
new file mode 100644
index 000000000000..b620542463df
--- /dev/null
+++ b/build/Modules/Umbraco.Build/Build-UmbracoDocs.ps1
@@ -0,0 +1,112 @@
+#
+
+function Build-UmbracoDocs
+{
+ $uenv = Get-UmbracoBuildEnv
+
+ $src = "$($uenv.SolutionRoot)\src"
+ $out = "$($uenv.SolutionRoot)\build.out"
+ $tmp = "$($uenv.SolutionRoot)\build.tmp"
+
+ $buildTemp = "$PSScriptRoot\temp"
+ $cache = 2
+
+ Prepare-Build -keep $uenv
+
+ ################ Do the UI docs
+ # get a temp clean node env (will restore)
+ Sandbox-Node $uenv
+
+ Write-Host "Executing gulp docs"
+
+ push-location "$($uenv.SolutionRoot)\src\Umbraco.Web.UI.Client"
+ write "node version is:" > $tmp\belle-docs.log
+ &node -v >> $tmp\belle-docs.log 2>&1
+ write "npm version is:" >> $tmp\belle-docs.log 2>&1
+ &npm -v >> $tmp\belle-docs.log 2>&1
+ write "executing npm install" >> $tmp\belle-docs.log 2>&1
+ &npm install >> $tmp\belle-docs.log 2>&1
+ write "executing bower install" >> $tmp\belle-docs.log 2>&1
+ &npm install -g bower >> $tmp\belle-docs.log 2>&1
+ write "installing gulp" >> $tmp\belle-docs.log 2>&1
+ &npm install -g gulp >> $tmp\belle-docs.log 2>&1
+ write "installing gulp-cli" >> $tmp\belle-docs.log 2>&1
+ &npm install -g gulp-cli --quiet >> $tmp\belle-docs.log 2>&1
+ write "building docs using gulp" >> $tmp\belle-docs.log 2>&1
+ &gulp docs >> $tmp\belle-docs.log 2>&1
+ pop-location
+
+ Write-Host "Completed gulp docs build"
+
+ # fixme - should we filter the log to find errors?
+ #get-content .\build.tmp\belle-docs.log | %{ if ($_ -match "build") { write $_}}
+
+ # change baseUrl
+ $baseUrl = "https://our.umbraco.org/apidocs/ui/"
+ $indexPath = "$src/Umbraco.Web.UI.Client/docs/api/index.html"
+ (Get-Content $indexPath).Replace("origin + location.href.substr(origin.length).replace(rUrl, indexFile)", "'$baseUrl'") `
+ | Set-Content $indexPath
+
+ # restore
+ Restore-Node
+
+ # zip
+ &$uenv.Zip a -tzip -r "$out\ui-docs.zip" "$src\Umbraco.Web.UI.Client\docs\api\*.*" `
+ > $null
+
+ ################ Do the c# docs
+
+ Write-Host "Build C# documentation"
+
+ # Build the solution in debug mode
+ # FIXME no only a simple compilation should be enough!
+ # FIXME we MUST handle msbuild & co error codes!
+ # FIXME deal with weird things in gitconfig?
+ #Build-Umbraco -Configuration Debug
+ Restore-NuGet $uenv
+ Compile-Umbraco $uenv "Debug" # FIXME different log file!
+ Restore-WebConfig "$src\Umbraco.Web.UI"
+
+ # ensure we have docfx
+ Get-DocFx $uenv $buildTemp
+
+ # clear
+ $docFxOutput = "$($uenv.SolutionRoot)\apidocs\_site"
+ if (test-path($docFxOutput))
+ {
+ Remove-Directory $docFxOutput
+ }
+
+ # run
+ $docFxJson = "$($uenv.SolutionRoot)\apidocs\docfx.json"
+ push-location "$($uenv.SolutionRoot)\build" # silly docfx.json wants this
+
+ Write-Host "Run DocFx metadata"
+ Write-Host "Logging to $tmp\docfx.metadata.log"
+ &$uenv.DocFx metadata $docFxJson > "$tmp\docfx.metadata.log"
+ Write-Host "Run DocFx build"
+ Write-Host "Logging to $tmp\docfx.build.log"
+ &$uenv.DocFx build $docFxJson > "$tmp\docfx.build.log"
+
+ pop-location
+
+ # zip
+ &$uenv.Zip a -tzip -r "$out\csharp-docs.zip" "$docFxOutput\*.*" `
+ > $null
+}
+
+function Get-DocFx($uenv, $buildTemp)
+{
+ $docFx = "$buildTemp\docfx"
+ if (-not (test-path $docFx))
+ {
+ $source = "https://github.com/dotnet/docfx/releases/download/v2.19.2/docfx.zip"
+ Write-Host "Download DocFx from $source"
+
+ Invoke-WebRequest $source -OutFile "$buildTemp\docfx.zip"
+
+ &$uenv.Zip x "$buildTemp\docfx.zip" -o"$buildTemp\docfx" -aos > $nul
+ Remove-File "$buildTemp\docfx.zip"
+ }
+ $uenv | add-member -memberType NoteProperty -name DocFx -value "$docFx\docfx.exe"
+}
\ No newline at end of file
diff --git a/build/Modules/Umbraco.Build/Get-UmbracoBuildEnv.ps1 b/build/Modules/Umbraco.Build/Get-UmbracoBuildEnv.ps1
new file mode 100644
index 000000000000..9b465fd78d25
--- /dev/null
+++ b/build/Modules/Umbraco.Build/Get-UmbracoBuildEnv.ps1
@@ -0,0 +1,182 @@
+#
+# Get-UmbracoBuildEnv
+# Gets the Umbraco build environment
+# Downloads tools if necessary
+#
+function Get-UmbracoBuildEnv
+{
+ # store tools in the module's directory
+ # and cache them for two days
+ $path = "$PSScriptRoot\temp"
+ $src = "$PSScriptRoot\..\..\..\src"
+ $cache = 2
+
+ if (-not (test-path $path))
+ {
+ mkdir $path > $null
+ }
+
+ # ensure we have NuGet
+ $nuget = "$path\nuget.exe"
+ $source = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
+ if ((test-path $nuget) -and ((ls $nuget).CreationTime -lt [DateTime]::Now.AddDays(-$cache)))
+ {
+ Remove-File $nuget
+ }
+ if (-not (test-path $nuget))
+ {
+ Write-Host "Download NuGet..."
+ Invoke-WebRequest $source -OutFile $nuget
+ }
+
+ # ensure we have 7-Zip
+ $sevenZip = "$path\7za.exe"
+ if ((test-path $sevenZip) -and ((ls $sevenZip).CreationTime -lt [DateTime]::Now.AddDays(-$cache)))
+ {
+ Remove-File $sevenZip
+ }
+ if (-not (test-path $sevenZip))
+ {
+ Write-Host "Download 7-Zip..."
+ &$nuget install 7-Zip.CommandLine -configFile "$src\NuGet.config" -OutputDirectory $path -Verbosity quiet
+ $dir = ls "$path\7-Zip.CommandLine.*" | sort -property Name -descending | select -first 1
+ $file = ls -path "$dir" -name 7za.exe -recurse
+ $file = ls -path "$dir" -name 7za.exe -recurse | select -first 1 #A select is because there is tools\7za.exe & tools\x64\7za.exe
+ mv "$dir\$file" $sevenZip
+ Remove-Directory $dir
+ }
+
+ # ensure we have vswhere
+ $vswhere = "$path\vswhere.exe"
+ if ((test-path $vswhere) -and ((ls $vswhere).CreationTime -lt [DateTime]::Now.AddDays(-$cache)))
+ {
+ Remove-File $vswhere
+ }
+ if (-not (test-path $vswhere))
+ {
+ Write-Host "Download VsWhere..."
+ &$nuget install vswhere -configFile "$src\NuGet.config" -OutputDirectory $path -Verbosity quiet
+ $dir = ls "$path\vswhere.*" | sort -property Name -descending | select -first 1
+ $file = ls -path "$dir" -name vswhere.exe -recurse
+ mv "$dir\$file" $vswhere
+ Remove-Directory $dir
+ }
+
+ # ensure we have semver
+ $semver = "$path\Semver.dll"
+ if ((test-path $semver) -and ((ls $semver).CreationTime -lt [DateTime]::Now.AddDays(-$cache)))
+ {
+ Remove-File $semver
+ }
+ if (-not (test-path $semver))
+ {
+ Write-Host "Download Semver..."
+ &$nuget install semver -configFile "$src\NuGet.config" -OutputDirectory $path -Verbosity quiet
+ $dir = ls "$path\semver.*" | sort -property Name -descending | select -first 1
+ $file = "$dir\lib\net452\Semver.dll"
+ if (-not (test-path $file))
+ {
+ Write-Error "Failed to file $file"
+ return
+ }
+ mv "$file" $semver
+ Remove-Directory $dir
+ }
+
+ try
+ {
+ [Reflection.Assembly]::LoadFile($semver) > $null
+ }
+ catch
+ {
+ Write-Error -Exception $_.Exception -Message "Failed to load $semver"
+ break
+ }
+
+ # ensure we have node
+ $node = "$path\node-v6.9.1-win-x86"
+ $source = "http://nodejs.org/dist/v6.9.1/node-v6.9.1-win-x86.7z"
+ if (-not (test-path $node))
+ {
+ Write-Host "Download Node..."
+ Invoke-WebRequest $source -OutFile "$path\node-v6.9.1-win-x86.7z"
+ &$sevenZip x "$path\node-v6.9.1-win-x86.7z" -o"$path" -aos > $nul
+ Remove-File "$path\node-v6.9.1-win-x86.7z"
+ }
+
+ # note: why? node already brings everything we need!
+ ## ensure we have npm
+ #$npm = "$path\npm.*"
+ #$getNpm = $true
+ #if (test-path $npm)
+ #{
+ # $getNpm = $false
+ # $tmpNpm = ls "$path\npm.*" | sort -property Name -descending | select -first 1
+ # if ($tmpNpm.CreationTime -lt [DateTime]::Now.AddDays(-$cache))
+ # {
+ # $getNpm = $true
+ # }
+ # else
+ # {
+ # $npm = $tmpNpm.ToString()
+ # }
+ #}
+ #if ($getNpm)
+ #{
+ # Write-Host "Download Npm..."
+ # &$nuget install npm -OutputDirectory $path -Verbosity quiet
+ # $npm = ls "$path\npm.*" | sort -property Name -descending | select -first 1
+ # $npm.CreationTime = [DateTime]::Now
+ # $npm = $npm.ToString()
+ #}
+
+ # find visual studio
+ # will not work on VSO but VSO does not need it
+ $vsPath = ""
+ $vsVer = ""
+ $msBuild = $null
+ &$vswhere | foreach {
+ if ($_.StartsWith("installationPath:")) { $vsPath = $_.SubString("installationPath:".Length).Trim() }
+ if ($_.StartsWith("installationVersion:")) { $vsVer = $_.SubString("installationVersion:".Length).Trim() }
+ }
+ if ($vsPath -ne "")
+ {
+ $vsVerParts = $vsVer.Split('.')
+ $vsMajor = [int]::Parse($vsVerParts[0])
+ $vsMinor = [int]::Parse($vsVerParts[1])
+ if ($vsMajor -eq 15) {
+ $msBuild = "$vsPath\MSBuild\$vsMajor.0\Bin"
+ }
+ elseif ($vsMajor -eq 14) {
+ $msBuild = "c:\Program Files (x86)\MSBuild\$vsMajor\Bin"
+ }
+ else
+ {
+ $msBuild = $null
+ }
+ }
+
+ $vs = $null
+ if ($msBuild)
+ {
+ $vs = new-object -typeName PsObject
+ $vs | add-member -memberType NoteProperty -name Path -value $vsPath
+ $vs | add-member -memberType NoteProperty -name Major -value $vsMajor
+ $vs | add-member -memberType NoteProperty -name Minor -value $vsMinor
+ $vs | add-member -memberType NoteProperty -name MsBuild -value "$msBuild\MsBuild.exe"
+ }
+
+ $solutionRoot = Get-FullPath "$PSScriptRoot\..\..\.."
+
+ $uenv = new-object -typeName PsObject
+ $uenv | add-member -memberType NoteProperty -name SolutionRoot -value $solutionRoot
+ $uenv | add-member -memberType NoteProperty -name VisualStudio -value $vs
+ $uenv | add-member -memberType NoteProperty -name NuGet -value $nuget
+ $uenv | add-member -memberType NoteProperty -name Zip -value $sevenZip
+ $uenv | add-member -memberType NoteProperty -name VsWhere -value $vswhere
+ $uenv | add-member -memberType NoteProperty -name Semver -value $semver
+ $uenv | add-member -memberType NoteProperty -name NodePath -value $node
+ #$uenv | add-member -memberType NoteProperty -name NpmPath -value $npm
+
+ return $uenv
+}
diff --git a/build/Modules/Umbraco.Build/Get-UmbracoVersion.ps1 b/build/Modules/Umbraco.Build/Get-UmbracoVersion.ps1
new file mode 100644
index 000000000000..a3ce784f146b
--- /dev/null
+++ b/build/Modules/Umbraco.Build/Get-UmbracoVersion.ps1
@@ -0,0 +1,26 @@
+#
+# Get-UmbracoVersion
+# Gets the Umbraco version
+#
+function Get-UmbracoVersion
+{
+ $uenv = Get-UmbracoBuildEnv
+
+ # parse SolutionInfo and retrieve the version string
+ $filepath = "$($uenv.SolutionRoot)\src\SolutionInfo.cs"
+ $text = [System.IO.File]::ReadAllText($filepath)
+ $match = [System.Text.RegularExpressions.Regex]::Matches($text, "AssemblyInformationalVersion\(`"(.+)?`"\)")
+ $version = $match.Groups[1]
+
+ # semver-parse the version string
+ $semver = [SemVer.SemVersion]::Parse($version)
+ $release = "" + $semver.Major + "." + $semver.Minor + "." + $semver.Patch
+
+ $versions = new-object -typeName PsObject
+ $versions | add-member -memberType NoteProperty -name Semver -value $semver
+ $versions | add-member -memberType NoteProperty -name Release -value $release
+ $versions | add-member -memberType NoteProperty -name Comment -value $semver.PreRelease
+ $versions | add-member -memberType NoteProperty -name Build -value $semver.Build
+
+ return $versions
+}
diff --git a/build/Modules/Umbraco.Build/Get-VisualStudio.ps1 b/build/Modules/Umbraco.Build/Get-VisualStudio.ps1
new file mode 100644
index 000000000000..cc88984eb210
--- /dev/null
+++ b/build/Modules/Umbraco.Build/Get-VisualStudio.ps1
@@ -0,0 +1,30 @@
+# finds msbuild
+function Get-VisualStudio($vswhere)
+{
+ $vsPath = ""
+ $vsVer = ""
+ &$vswhere | foreach {
+ if ($_.StartsWith("installationPath:")) { $vsPath = $_.SubString("installationPath:".Length).Trim() }
+ if ($_.StartsWith("installationVersion:")) { $vsVer = $_.SubString("installationVersion:".Length).Trim() }
+ }
+ if ($vsPath -eq "") { return $null }
+
+ $vsVerParts = $vsVer.Split('.')
+ $vsMajor = [int]::Parse($vsVerParts[0])
+ $vsMinor = [int]::Parse($vsVerParts[1])
+ if ($vsMajor -eq 15) {
+ $msBuild = "$vsPath\MSBuild\$vsMajor.$vsMinor\Bin"
+ }
+ elseif ($vsMajor -eq 14) {
+ $msBuild = "c:\Program Files (x86)\MSBuild\$vsMajor\Bin"
+ }
+ else { return $null }
+ $msBuild = "$msBuild\MsBuild.exe"
+
+ $vs = new-object -typeName PsObject
+ $vs | add-member -memberType NoteProperty -name Path -value $vsPath
+ $vs | add-member -memberType NoteProperty -name Major -value $vsMajor
+ $vs | add-member -memberType NoteProperty -name Minor -value $vsMinor
+ $vs | add-member -memberType NoteProperty -name MsBuild -value $msBuild
+ return $vs
+}
diff --git a/build/Modules/Umbraco.Build/Set-UmbracoContinuousVersion.ps1 b/build/Modules/Umbraco.Build/Set-UmbracoContinuousVersion.ps1
new file mode 100644
index 000000000000..8996777292fd
--- /dev/null
+++ b/build/Modules/Umbraco.Build/Set-UmbracoContinuousVersion.ps1
@@ -0,0 +1,30 @@
+#
+# Set-UmbracoContinuousVersion
+# Sets the Umbraco version for continuous integration
+#
+# -Version
+# where is a Semver valid version
+# eg 1.2.3, 1.2.3-alpha, 1.2.3-alpha+456
+#
+# -BuildNumber
+# where is a string coming from the build server
+# eg 34, 126, 1
+#
+function Set-UmbracoContinuousVersion
+{
+ param (
+ [Parameter(Mandatory=$true)]
+ [string]
+ $version,
+ [Parameter(Mandatory=$true)]
+ [string]
+ $buildNumber
+ )
+
+ Write-Host "Version is currently set to $version"
+
+ $umbracoVersion = "$($version.Trim())-alpha$($buildNumber)"
+ Write-Host "Setting Umbraco Version to $umbracoVersion"
+
+ Set-UmbracoVersion $umbracoVersion
+}
\ No newline at end of file
diff --git a/build/Modules/Umbraco.Build/Set-UmbracoVersion.ps1 b/build/Modules/Umbraco.Build/Set-UmbracoVersion.ps1
new file mode 100644
index 000000000000..19681dcba026
--- /dev/null
+++ b/build/Modules/Umbraco.Build/Set-UmbracoVersion.ps1
@@ -0,0 +1,117 @@
+#
+# Set-UmbracoVersion
+# Sets the Umbraco version
+#
+# -Version
+# where is a Semver valid version
+# eg 1.2.3, 1.2.3-alpha, 1.2.3-alpha+456
+#
+function Set-UmbracoVersion
+{
+ param (
+ [Parameter(Mandatory=$true)]
+ [string]
+ $version
+ )
+
+ $uenv = Get-UmbracoBuildEnv
+
+ try
+ {
+ [Reflection.Assembly]::LoadFile($uenv.Semver) > $null
+ }
+ catch
+ {
+ Write-Error "Failed to load $uenv.Semver"
+ break
+ }
+
+ # validate input
+ $ok = [Regex]::Match($version, "^[0-9]+\.[0-9]+\.[0-9]+(\-[a-z0-9]+)?(\+[0-9]+)?$")
+ if (-not $ok.Success)
+ {
+ Write-Error "Invalid version $version"
+ break
+ }
+
+ # parse input
+ try
+ {
+ $semver = [SemVer.SemVersion]::Parse($version)
+ }
+ catch
+ {
+ Write-Error "Invalid version $version"
+ break
+ }
+
+ #
+ $release = "" + $semver.Major + "." + $semver.Minor + "." + $semver.Patch
+
+ # edit files and set the proper versions and dates
+ Write-Host "Update UmbracoVersion.cs"
+ Replace-FileText "$($uenv.SolutionRoot)\src\Umbraco.Core\Configuration\UmbracoVersion.cs" `
+ "(\d+)\.(\d+)\.(\d+)(.(\d+))?" `
+ "$release"
+ Replace-FileText "$($uenv.SolutionRoot)\src\Umbraco.Core\Configuration\UmbracoVersion.cs" `
+ "CurrentComment { get { return `"(.+)`"" `
+ "CurrentComment { get { return `"$($semver.PreRelease)`""
+ Write-Host "Update SolutionInfo.cs"
+ Replace-FileText "$($uenv.SolutionRoot)\src\SolutionInfo.cs" `
+ "AssemblyFileVersion\(`"(.+)?`"\)" `
+ "AssemblyFileVersion(`"$release`")"
+ Replace-FileText "$($uenv.SolutionRoot)\src\SolutionInfo.cs" `
+ "AssemblyInformationalVersion\(`"(.+)?`"\)" `
+ "AssemblyInformationalVersion(`"$semver`")"
+ $year = [System.DateTime]::Now.ToString("yyyy")
+ Replace-FileText "$($uenv.SolutionRoot)\src\SolutionInfo.cs" `
+ "AssemblyCopyright\(`"Copyright © Umbraco (\d{4})`"\)" `
+ "AssemblyCopyright(`"Copyright © Umbraco $year`")"
+
+ # edit csproj and set IIS Express port number
+ # this is a raw copy of ReplaceIISExpressPortNumber.exe
+ # it probably can be achieved in a much nicer way - l8tr
+ $source = @"
+ using System;
+ using System.IO;
+ using System.Xml;
+ using System.Globalization;
+
+ namespace Umbraco
+ {
+ public static class PortUpdater
+ {
+ public static void Update(string path, string release)
+ {
+ XmlDocument xmlDocument = new XmlDocument();
+ string fullPath = Path.GetFullPath(path);
+ xmlDocument.Load(fullPath);
+ int result = 1;
+ int.TryParse(release.Replace(`".`", `"`"), out result);
+ while (result < 1024)
+ result *= 10;
+ XmlNode xmlNode1 = xmlDocument.GetElementsByTagName(`"IISUrl`").Item(0);
+ if (xmlNode1 != null)
+ xmlNode1.InnerText = `"http://localhost:`" + (object) result;
+ XmlNode xmlNode2 = xmlDocument.GetElementsByTagName(`"DevelopmentServerPort`").Item(0);
+ if (xmlNode2 != null)
+ xmlNode2.InnerText = result.ToString((IFormatProvider) CultureInfo.InvariantCulture);
+ xmlDocument.Save(fullPath);
+ }
+ }
+ }
+"@
+
+ $assem = (
+ "System.Xml",
+ "System.IO",
+ "System.Globalization"
+ )
+
+ Write-Host "Update Umbraco.Web.UI.csproj"
+ add-type -referencedAssemblies $assem -typeDefinition $source -language CSharp
+ $csproj = "$($uenv.SolutionRoot)\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj"
+ [Umbraco.PortUpdater]::Update($csproj, $release)
+
+ return $semver
+}
diff --git a/build/Modules/Umbraco.Build/Umbraco.Build.psm1 b/build/Modules/Umbraco.Build/Umbraco.Build.psm1
new file mode 100644
index 000000000000..6b9cdb28da75
--- /dev/null
+++ b/build/Modules/Umbraco.Build/Umbraco.Build.psm1
@@ -0,0 +1,615 @@
+
+# Umbraco.Build.psm1
+#
+# $env:PSModulePath = "$pwd\build\Modules\;$env:PSModulePath"
+# Import-Module Umbraco.Build -Force -DisableNameChecking
+#
+# PowerShell Modules:
+# https://msdn.microsoft.com/en-us/library/dd878324%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
+#
+# PowerShell Module Manifest:
+# https://msdn.microsoft.com/en-us/library/dd878337%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
+#
+# See also
+# http://www.powershellmagazine.com/2014/08/15/pstip-taking-control-of-verbose-and-debug-output-part-5/
+
+
+. "$PSScriptRoot\Utilities.ps1"
+. "$PSScriptRoot\Get-VisualStudio.ps1"
+
+. "$PSScriptRoot\Get-UmbracoBuildEnv.ps1"
+. "$PSScriptRoot\Set-UmbracoVersion.ps1"
+. "$PSScriptRoot\Set-UmbracoContinuousVersion.ps1"
+. "$PSScriptRoot\Get-UmbracoVersion.ps1"
+. "$PSScriptRoot\Verify-NuGet.ps1"
+
+. "$PSScriptRoot\Build-UmbracoDocs.ps1"
+
+#
+# Prepares the build
+#
+function Prepare-Build
+{
+ param (
+ $uenv, # an Umbraco build environment (see Get-UmbracoBuildEnv)
+
+ [Alias("k")]
+ [switch]
+ $keep = $false
+ )
+
+ Write-Host ">> Prepare Build"
+
+ $src = "$($uenv.SolutionRoot)\src"
+ $tmp = "$($uenv.SolutionRoot)\build.tmp"
+ $out = "$($uenv.SolutionRoot)\build.out"
+
+ # clear
+ Write-Host "Clear folders and files"
+
+ Remove-Directory "$src\Umbraco.Web.UI.Client\bower_components"
+
+ if (-not $keep)
+ {
+ Remove-Directory "$tmp"
+ Remove-Directory "$out"
+ }
+
+ if (-not (Test-Path "$tmp"))
+ {
+ mkdir "$tmp" > $null
+ }
+ if (-not (Test-Path "$out"))
+ {
+ mkdir "$out" > $null
+ }
+
+ # ensure proper web.config
+ $webUi = "$src\Umbraco.Web.UI"
+ Store-WebConfig $webUi
+ Write-Host "Create clean web.config"
+ Copy-File "$webUi\web.Template.config" "$webUi\web.config"
+}
+
+function Clear-EnvVar($var)
+{
+ $value = [Environment]::GetEnvironmentVariable($var)
+ if (test-path "env:$var") { rm "env:$var" }
+ return $value
+}
+
+function Set-EnvVar($var, $value)
+{
+ if ($value)
+ {
+ [Environment]::SetEnvironmentVariable($var, $value)
+ }
+ else
+ {
+ if (test-path "env:$var") { rm "env:$var" }
+ }
+}
+
+function Sandbox-Node
+{
+ param (
+ $uenv # an Umbraco build environment (see Get-UmbracoBuildEnv)
+ )
+
+ $global:node_path = $env:path
+ $nodePath = $uenv.NodePath
+ $gitExe = (get-command git).Source
+ $gitPath = [System.IO.Path]::GetDirectoryName($gitExe)
+ $env:path = "$nodePath;$gitPath"
+
+ $global:node_nodepath = Clear-EnvVar "NODEPATH"
+ $global:node_npmcache = Clear-EnvVar "NPM_CONFIG_CACHE"
+ $global:node_npmprefix = Clear-EnvVar "NPM_CONFIG_PREFIX"
+}
+
+function Restore-Node
+{
+ $env:path = $node_path
+
+ Set-EnvVar "NODEPATH" $node_nodepath
+ Set-EnvVar "NPM_CONFIG_CACHE" $node_npmcache
+ Set-EnvVar "NPM_CONFIG_PREFIX" $node_npmprefix
+}
+
+#
+# Builds the Belle UI project
+#
+function Compile-Belle
+{
+ param (
+ $uenv, # an Umbraco build environment (see Get-UmbracoBuildEnv)
+ $version # an Umbraco version object (see Get-UmbracoVersion)
+ )
+
+ $tmp = "$($uenv.SolutionRoot)\build.tmp"
+ $src = "$($uenv.SolutionRoot)\src"
+
+ Write-Host ">> Compile Belle"
+ Write-Host "Logging to $tmp\belle.log"
+
+ # get a temp clean node env (will restore)
+ Sandbox-Node $uenv
+
+ push-location "$($uenv.SolutionRoot)\src\Umbraco.Web.UI.Client"
+ write "node version is:" > $tmp\belle.log
+ &node -v >> $tmp\belle.log 2>&1
+ write "npm version is:" >> $tmp\belle.log 2>&1
+ &npm -v >> $tmp\belle.log 2>&1
+ write "cleaning npm cache" >> $tmp\belle.log 2>&1
+ &npm cache clean >> $tmp\belle.log 2>&1
+ write "installing bower" >> $tmp\belle.log 2>&1
+ &npm install -g bower >> $tmp\belle.log 2>&1
+ write "installing gulp" >> $tmp\belle.log 2>&1
+ &npm install -g gulp >> $tmp\belle.log 2>&1
+ write "installing gulp-cli" >> $tmp\belle.log 2>&1
+ &npm install -g gulp-cli --quiet >> $tmp\belle.log 2>&1
+ write "executing npm install" >> $tmp\belle.log 2>&1
+ &npm install >> $tmp\belle.log 2>&1
+ write "executing gulp build for version $version" >> $tmp\belle.log 2>&1
+ &gulp build --buildversion=$version.Release >> $tmp\belle.log 2>&1
+ pop-location
+
+ # fixme - should we filter the log to find errors?
+ #get-content .\build.tmp\belle.log | %{ if ($_ -match "build") { write $_}}
+
+ # restore
+ Restore-Node
+
+ # setting node_modules folder to hidden
+ # used to prevent VS13 from crashing on it while loading the websites project
+ # also makes sure aspnet compiler does not try to handle rogue files and chokes
+ # in VSO with Microsoft.VisualC.CppCodeProvider -related errors
+ # use get-item -force 'cos it might be hidden already
+ write "Set hidden attribute on node_modules"
+ $dir = get-item -force "$src\Umbraco.Web.UI.Client\node_modules"
+ $dir.Attributes = $dir.Attributes -bor ([System.IO.FileAttributes]::Hidden)
+}
+
+#
+# Compiles Umbraco
+#
+function Compile-Umbraco
+{
+ param (
+ $uenv, # an Umbraco build environment (see Get-UmbracoBuildEnv)
+ [string] $buildConfiguration = "Release"
+ )
+
+ $src = "$($uenv.SolutionRoot)\src"
+ $tmp = "$($uenv.SolutionRoot)\build.tmp"
+ $out = "$($uenv.SolutionRoot)\build.out"
+
+ if ($uenv.VisualStudio -eq $null)
+ {
+ Write-Error "Build environment does not provide VisualStudio."
+ break
+ }
+
+ $toolsVersion = "4.0"
+ if ($uenv.VisualStudio.Major -eq 15)
+ {
+ $toolsVersion = "15.0"
+ }
+
+ Write-Host ">> Compile Umbraco"
+ Write-Host "Logging to $tmp\msbuild.umbraco.log"
+
+ # beware of the weird double \\ at the end of paths
+ # see http://edgylogic.com/blog/powershell-and-external-commands-done-right/
+ &$uenv.VisualStudio.MsBuild "$src\Umbraco.Web.UI\Umbraco.Web.UI.csproj" `
+ /p:WarningLevel=0 `
+ /p:Configuration=$buildConfiguration `
+ /p:Platform=AnyCPU `
+ /p:UseWPP_CopyWebApplication=True `
+ /p:PipelineDependsOnBuild=False `
+ /p:OutDir=$tmp\bin\\ `
+ /p:WebProjectOutputDir=$tmp\WebApp\\ `
+ /p:Verbosity=minimal `
+ /t:Clean`;Rebuild `
+ /tv:$toolsVersion `
+ /p:UmbracoBuild=True `
+ > $tmp\msbuild.umbraco.log
+
+ # /p:UmbracoBuild tells the csproj that we are building from PS
+}
+
+#
+# Prepare Tests
+#
+function Prepare-Tests
+{
+ param (
+ $uenv # an Umbraco build environment (see Get-UmbracoBuildEnv)
+ )
+
+ $src = "$($uenv.SolutionRoot)\src"
+ $tmp = "$($uenv.SolutionRoot)\build.tmp"
+
+ Write-Host ">> Prepare Tests"
+
+ # fixme - idea is to avoid rebuilding everything for tests
+ # but because of our weird assembly versioning (with .* stuff)
+ # everything gets rebuilt all the time...
+ #Copy-Files "$tmp\bin" "." "$tmp\tests"
+
+ # data
+ Write-Host "Copy data files"
+ if (-Not (Test-Path -Path "$tmp\tests\Packaging" ) )
+ {
+ Write-Host "Create packaging directory"
+ mkdir "$tmp\tests\Packaging" > $null
+ }
+ Copy-Files "$src\Umbraco.Tests\Packaging\Packages" "*" "$tmp\tests\Packaging\Packages"
+
+ # required for package install tests
+ if (-Not (Test-Path -Path "$tmp\tests\bin" ) )
+ {
+ Write-Host "Create bin directory"
+ mkdir "$tmp\tests\bin" > $null
+ }
+}
+
+#
+# Compiles Tests
+#
+function Compile-Tests
+{
+ param (
+ $uenv # an Umbraco build environment (see Get-UmbracoBuildEnv)
+ )
+
+ $src = "$($uenv.SolutionRoot)\src"
+ $tmp = "$($uenv.SolutionRoot)\build.tmp"
+ $out = "$tmp\tests"
+
+ $buildConfiguration = "Release"
+
+ if ($uenv.VisualStudio -eq $null)
+ {
+ Write-Error "Build environment does not provide VisualStudio."
+ break
+ }
+
+ $toolsVersion = "4.0"
+ if ($uenv.VisualStudio.Major -eq 15)
+ {
+ $toolsVersion = "15.0"
+ }
+
+ Write-Host ">> Compile Tests"
+ Write-Host "Logging to $tmp\msbuild.tests.log"
+
+ # beware of the weird double \\ at the end of paths
+ # see http://edgylogic.com/blog/powershell-and-external-commands-done-right/
+ &$uenv.VisualStudio.MsBuild "$src\Umbraco.Tests\Umbraco.Tests.csproj" `
+ /p:WarningLevel=0 `
+ /p:Configuration=$buildConfiguration `
+ /p:Platform=AnyCPU `
+ /p:UseWPP_CopyWebApplication=True `
+ /p:PipelineDependsOnBuild=False `
+ /p:OutDir=$out\\ `
+ /p:Verbosity=minimal `
+ /t:Build `
+ /tv:$toolsVersion `
+ /p:UmbracoBuild=True `
+ /p:NugetPackages=$src\packages `
+ > $tmp\msbuild.tests.log
+
+ # /p:UmbracoBuild tells the csproj that we are building from PS
+}
+
+#
+# Cleans things up and prepare files after compilation
+#
+function Prepare-Packages
+{
+ param (
+ $uenv # an Umbraco build environment (see Get-UmbracoBuildEnv)
+ )
+
+ Write-Host ">> Prepare Packages"
+
+ $src = "$($uenv.SolutionRoot)\src"
+ $tmp = "$($uenv.SolutionRoot)\build.tmp"
+ $out = "$($uenv.SolutionRoot)\build.out"
+
+ $buildConfiguration = "Release"
+
+ # restore web.config
+ Restore-WebConfig "$src\Umbraco.Web.UI"
+
+ # cleanup build
+ Write-Host "Clean build"
+ Remove-File "$tmp\bin\*.dll.config"
+ Remove-File "$tmp\WebApp\bin\*.dll.config"
+
+ # cleanup presentation
+ Write-Host "Cleanup presentation"
+ Remove-Directory "$tmp\WebApp\umbraco.presentation"
+
+ # create directories
+ Write-Host "Create directories"
+ mkdir "$tmp\Configs" > $null
+ mkdir "$tmp\Configs\Lang" > $null
+ mkdir "$tmp\WebApp\App_Data" > $null
+ #mkdir "$tmp\WebApp\Media" > $null
+ #mkdir "$tmp\WebApp\Views" > $null
+
+ # copy various files
+ Write-Host "Copy xml documentation"
+ cp -force "$tmp\bin\*.xml" "$tmp\WebApp\bin"
+
+ Write-Host "Copy transformed configs and langs"
+ # note: exclude imageprocessor/*.config as imageprocessor pkg installs them
+ Copy-Files "$tmp\WebApp\config" "*.config" "$tmp\Configs" `
+ { -not $_.RelativeName.StartsWith("imageprocessor") }
+ Copy-Files "$tmp\WebApp\config" "*.js" "$tmp\Configs"
+ Copy-Files "$tmp\WebApp\config\lang" "*.xml" "$tmp\Configs\Lang"
+ Copy-File "$tmp\WebApp\web.config" "$tmp\Configs\web.config.transform"
+
+ Write-Host "Copy transformed web.config"
+ Copy-File "$src\Umbraco.Web.UI\web.$buildConfiguration.Config.transformed" "$tmp\WebApp\web.config"
+
+ # offset the modified timestamps on all umbraco dlls, as WebResources
+ # break if date is in the future, which, due to timezone offsets can happen.
+ Write-Host "Offset dlls timestamps"
+ ls -r "$tmp\*.dll" | foreach {
+ $_.CreationTime = $_.CreationTime.AddHours(-11)
+ $_.LastWriteTime = $_.LastWriteTime.AddHours(-11)
+ }
+
+ # copy libs
+ Write-Host "Copy SqlCE libraries"
+ Copy-Files "$src\packages\SqlServerCE.4.0.0.1" "*.*" "$tmp\bin" `
+ { -not $_.Extension.StartsWith(".nu") -and -not $_.RelativeName.StartsWith("lib\") }
+ Copy-Files "$src\packages\SqlServerCE.4.0.0.1" "*.*" "$tmp\WebApp\bin" `
+ { -not $_.Extension.StartsWith(".nu") -and -not $_.RelativeName.StartsWith("lib\") }
+
+ # copy Belle
+ Write-Host "Copy Belle"
+ Copy-Files "$src\Umbraco.Web.UI\umbraco\assets" "*" "$tmp\WebApp\umbraco\assets"
+ Copy-Files "$src\Umbraco.Web.UI\umbraco\js" "*" "$tmp\WebApp\umbraco\js"
+ Copy-Files "$src\Umbraco.Web.UI\umbraco\lib" "*" "$tmp\WebApp\umbraco\lib"
+ Copy-Files "$src\Umbraco.Web.UI\umbraco\views" "*" "$tmp\WebApp\umbraco\views"
+
+}
+
+#
+# Creates the Zip packages
+#
+function Package-Zip
+{
+ param (
+ $uenv # an Umbraco build environment (see Get-UmbracoBuildEnv)
+ )
+
+ Write-Host ">> Create Zip packages"
+
+ $src = "$($uenv.SolutionRoot)\src"
+ $tmp = "$($uenv.SolutionRoot)\build.tmp"
+ $out = "$($uenv.SolutionRoot)\build.out"
+
+ Write-Host "Zip all binaries"
+ &$uenv.Zip a -r "$out\UmbracoCms.AllBinaries.$($version.Semver).zip" `
+ "$tmp\bin\*" `
+ "-x!dotless.Core.*" `
+ > $null
+
+ Write-Host "Zip cms"
+ &$uenv.Zip a -r "$out\UmbracoCms.$($version.Semver).zip" `
+ "$tmp\WebApp\*" `
+ "-x!dotless.Core.*" "-x!Content_Types.xml" "-x!*.pdb"`
+ > $null
+}
+
+#
+# Prepares NuGet
+#
+function Prepare-NuGet
+{
+ param (
+ $uenv # an Umbraco build environment (see Get-UmbracoBuildEnv)
+ )
+
+ Write-Host ">> Prepare NuGet"
+
+ $src = "$($uenv.SolutionRoot)\src"
+ $tmp = "$($uenv.SolutionRoot)\build.tmp"
+ $out = "$($uenv.SolutionRoot)\build.out"
+
+ # add Web.config transform files to the NuGet package
+ Write-Host "Add web.config transforms to NuGet package"
+ mv "$tmp\WebApp\Views\Web.config" "$tmp\WebApp\Views\Web.config.transform"
+
+ # fixme - that one does not exist in .bat build either?
+ #mv "$tmp\WebApp\Xslt\Web.config" "$tmp\WebApp\Xslt\Web.config.transform"
+}
+
+#
+# Restores NuGet
+#
+function Restore-NuGet
+{
+ param (
+ $uenv # an Umbraco build environment (see Get-UmbracoBuildEnv)
+ )
+
+ $src = "$($uenv.SolutionRoot)\src"
+ $tmp = "$($uenv.SolutionRoot)\build.tmp"
+
+ Write-Host ">> Restore NuGet"
+ Write-Host "Logging to $tmp\nuget.restore.log"
+
+ &$uenv.NuGet restore "$src\Umbraco.sln" -configfile "$src\NuGet.config" > "$tmp\nuget.restore.log"
+}
+
+#
+# Copies the Azure Gallery script to output
+#
+function Prepare-AzureGallery
+{
+ param (
+ $uenv # an Umbraco build environment (see Get-UmbracoBuildEnv)
+ )
+
+ $src = "$($uenv.SolutionRoot)\src"
+ $tmp = "$($uenv.SolutionRoot)\build.tmp"
+ $out = "$($uenv.SolutionRoot)\build.out"
+ $psScript = "$($uenv.SolutionRoot)\build\azuregalleryrelease.ps1"
+
+ Write-Host ">> Copy azuregalleryrelease.ps1 to output folder"
+ Copy-Item $psScript $out
+}
+
+#
+# Creates the NuGet packages
+#
+function Package-NuGet
+{
+ param (
+ $uenv, # an Umbraco build environment (see Get-UmbracoBuildEnv)
+ $version # an Umbraco version object (see Get-UmbracoVersion)
+ )
+
+ $src = "$($uenv.SolutionRoot)\src"
+ $tmp = "$($uenv.SolutionRoot)\build.tmp"
+ $out = "$($uenv.SolutionRoot)\build.out"
+ $nuspecs = "$($uenv.SolutionRoot)\build\NuSpecs"
+
+ Write-Host ">> Create NuGet packages"
+
+ # see https://docs.microsoft.com/en-us/nuget/schema/nuspec
+ # note - warnings about SqlCE native libs being outside of 'lib' folder,
+ # nothing much we can do about it as it's intentional yet there does not
+ # seem to be a way to disable the warning
+
+ &$uenv.NuGet Pack "$nuspecs\UmbracoCms.Core.nuspec" `
+ -Properties BuildTmp="$tmp" `
+ -Version $version.Semver.ToString() `
+ -Symbols -Verbosity quiet -outputDirectory $out
+
+ &$uenv.NuGet Pack "$nuspecs\UmbracoCms.nuspec" `
+ -Properties BuildTmp="$tmp" `
+ -Version $version.Semver.ToString() `
+ -Verbosity quiet -outputDirectory $out
+}
+
+#
+# Builds Umbraco
+#
+function Build-Umbraco
+{
+ [CmdletBinding()]
+ param (
+ [string]
+ $target = "all",
+ [string]
+ $buildConfiguration = "Release"
+ )
+
+ $target = $target.ToLowerInvariant()
+ Write-Host ">> Build-Umbraco <$target> <$buildConfiguration>"
+
+ Write-Host "Get Build Environment"
+ $uenv = Get-UmbracoBuildEnv
+
+ Write-Host "Get Version"
+ $version = Get-UmbracoVersion
+ Write-Host "Version $($version.Semver)"
+
+ if ($target -eq "pre-build")
+ {
+ Prepare-Build $uenv
+ #Compile-Belle $uenv $version
+
+ # set environment variables
+ $env:UMBRACO_VERSION=$version.Semver.ToString()
+ $env:UMBRACO_RELEASE=$version.Release
+ $env:UMBRACO_COMMENT=$version.Comment
+ $env:UMBRACO_BUILD=$version.Build
+
+ # set environment variable for VSO
+ # https://github.com/Microsoft/vsts-tasks/issues/375
+ # https://github.com/Microsoft/vsts-tasks/blob/master/docs/authoring/commands.md
+ Write-Host ("##vso[task.setvariable variable=UMBRACO_VERSION;]$($version.Semver.ToString())")
+ Write-Host ("##vso[task.setvariable variable=UMBRACO_RELEASE;]$($version.Release)")
+ Write-Host ("##vso[task.setvariable variable=UMBRACO_COMMENT;]$($version.Comment)")
+ Write-Host ("##vso[task.setvariable variable=UMBRACO_BUILD;]$($version.Build)")
+
+ Write-Host ("##vso[task.setvariable variable=UMBRACO_TMP;]$($uenv.SolutionRoot)\build.tmp")
+ }
+ elseif ($target -eq "pre-tests")
+ {
+ Prepare-Tests $uenv
+ }
+ elseif ($target -eq "compile-tests")
+ {
+ Compile-Tests $uenv
+ }
+ elseif ($target -eq "compile-umbraco")
+ {
+ Compile-Umbraco $uenv $buildConfiguration
+ }
+ elseif ($target -eq "pre-packages")
+ {
+ Prepare-Packages $uenv
+ }
+ elseif ($target -eq "pre-nuget")
+ {
+ Prepare-NuGet $uenv
+ }
+ elseif ($target -eq "restore-nuget")
+ {
+ Restore-NuGet $uenv
+ }
+ elseif ($target -eq "pkg-zip")
+ {
+ Package-Zip $uenv
+ }
+ elseif ($target -eq "compile-belle")
+ {
+ Compile-Belle $uenv $version
+ }
+ elseif ($target -eq "prepare-azuregallery")
+ {
+ Prepare-AzureGallery $uenv
+ }
+ elseif ($target -eq "all")
+ {
+ Prepare-Build $uenv
+ Restore-NuGet $uenv
+ Compile-Belle $uenv $version
+ Compile-Umbraco $uenv $buildConfiguration
+ Prepare-Tests $uenv
+ Compile-Tests $uenv
+ # not running tests...
+ Prepare-Packages $uenv
+ Package-Zip $uenv
+ Verify-NuGet $uenv
+ Prepare-NuGet $uenv
+ Package-NuGet $uenv $version
+ Prepare-AzureGallery $uenv
+ }
+ else
+ {
+ Write-Error "Unsupported target `"$target`"."
+ }
+}
+
+#
+# export functions
+#
+Export-ModuleMember -function Get-UmbracoBuildEnv
+Export-ModuleMember -function Set-UmbracoVersion
+Export-ModuleMember -function Set-UmbracoContinuousVersion
+Export-ModuleMember -function Get-UmbracoVersion
+Export-ModuleMember -function Build-Umbraco
+Export-ModuleMember -function Build-UmbracoDocs
+Export-ModuleMember -function Verify-NuGet
+
+#eof
\ No newline at end of file
diff --git a/build/Modules/Umbraco.Build/Utilities.ps1 b/build/Modules/Umbraco.Build/Utilities.ps1
new file mode 100644
index 000000000000..8ca24885cd98
--- /dev/null
+++ b/build/Modules/Umbraco.Build/Utilities.ps1
@@ -0,0 +1,95 @@
+# returns the full path if $file is relative to $pwd
+function Get-FullPath($file)
+{
+ $path = [System.IO.Path]::Combine($pwd, $file)
+ $path = [System.IO.Path]::GetFullPath($path)
+ return $path
+}
+
+# removes a directory, doesn't complain if it does not exist
+function Remove-Directory($dir)
+{
+ remove-item $dir -force -recurse -errorAction SilentlyContinue > $null
+}
+
+# removes a file, doesn't complain if it does not exist
+function Remove-File($file)
+{
+ remove-item $file -force -errorAction SilentlyContinue > $null
+}
+
+# copies a file, creates target dir if needed
+function Copy-File($source, $target)
+{
+ $ignore = new-item -itemType file -path $target -force
+ cp -force $source $target
+}
+
+# copies files to a directory
+function Copy-Files($source, $select, $target, $filter)
+{
+ $files = ls -r "$source\$select"
+ $files | foreach {
+ $relative = $_.FullName.SubString($source.Length+1)
+ $_ | add-member -memberType NoteProperty -name RelativeName -value $relative
+ }
+ if ($filter -ne $null) {
+ $files = $files | where $filter
+ }
+ $files |
+ foreach {
+ if ($_.PsIsContainer) {
+ $ignore = new-item -itemType directory -path "$target\$($_.RelativeName)" -force
+ }
+ else {
+ Copy-File $_.FullName "$target\$($_.RelativeName)"
+ }
+ }
+}
+
+# regex-replaces content in a file
+function Replace-FileText($filename, $source, $replacement)
+{
+ $filepath = Get-FullPath $filename
+ $text = [System.IO.File]::ReadAllText($filepath)
+ $text = [System.Text.RegularExpressions.Regex]::Replace($text, $source, $replacement)
+ $utf8bom = New-Object System.Text.UTF8Encoding $true
+ [System.IO.File]::WriteAllText($filepath, $text, $utf8bom)
+}
+
+# store web.config
+function Store-WebConfig($webUi)
+{
+ if (test-path "$webUi\web.config")
+ {
+ if (test-path "$webUi\web.config.temp-build")
+ {
+ Write-Host "Found existing web.config.temp-build"
+ $i = 0
+ while (test-path "$webUi\web.config.temp-build.$i")
+ {
+ $i = $i + 1
+ }
+ Write-Host "Save existing web.config as web.config.temp-build.$i"
+ Write-Host "(WARN: the original web.config.temp-build will be restored during post-build)"
+ mv "$webUi\web.config" "$webUi\web.config.temp-build.$i"
+ }
+ else
+ {
+ Write-Host "Save existing web.config as web.config.temp-build"
+ Write-Host "(will be restored during post-build)"
+ mv "$webUi\web.config" "$webUi\web.config.temp-build"
+ }
+ }
+}
+
+# restore web.config
+function Restore-WebConfig($webUi)
+{
+ if (test-path "$webUi\web.config.temp-build")
+ {
+ Write-Host "Restoring existing web.config"
+ Remove-File "$webUi\web.config"
+ mv "$webUi\web.config.temp-build" "$webUi\web.config"
+ }
+}
\ No newline at end of file
diff --git a/build/Modules/Umbraco.Build/Verify-NuGet.ps1 b/build/Modules/Umbraco.Build/Verify-NuGet.ps1
new file mode 100644
index 000000000000..1a2239393ccb
--- /dev/null
+++ b/build/Modules/Umbraco.Build/Verify-NuGet.ps1
@@ -0,0 +1,444 @@
+#
+# Verify-NuGet
+#
+
+function Format-Dependency
+{
+ param ( $d )
+
+ $m = $d.Id + " "
+ if ($d.MinInclude) { $m = $m + "[" }
+ else { $m = $m + "(" }
+ $m = $m + $d.MinVersion
+ if ($d.MaxVersion -ne $d.MinVersion) { $m = $m + "," + $d.MaxVersion }
+ if ($d.MaxInclude) { $m = $m + "]" }
+ else { $m = $m + ")" }
+
+ return $m
+}
+
+function Write-NuSpec
+{
+ param ( $name, $deps )
+
+ Write-Host ""
+ Write-Host "$name NuSpec dependencies:"
+
+ foreach ($d in $deps)
+ {
+ $m = Format-Dependency $d
+ Write-Host " $m"
+ }
+}
+
+function Write-Package
+{
+ param ( $name, $pkgs )
+
+ Write-Host ""
+ Write-Host "$name packages:"
+
+ foreach ($p in $pkgs)
+ {
+ Write-Host " $($p.Id) $($p.Version)"
+ }
+}
+
+function Verify-NuGet
+{
+ param (
+ $uenv # an Umbraco build environment (see Get-UmbracoBuildEnv)
+ )
+
+ if ($uenv -eq $null)
+ {
+ $uenv = Get-UmbracoBuildEnv
+ }
+
+ $source = @"
+
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.IO;
+ using System.Xml;
+ using System.Xml.Serialization;
+ using Semver;
+
+ namespace Umbraco.Build
+ {
+ public class NuGet
+ {
+ public static Dependency[] GetNuSpecDependencies(string filename)
+ {
+ NuSpec nuspec;
+ var serializer = new XmlSerializer(typeof(NuSpec));
+ using (var reader = new StreamReader(filename))
+ {
+ nuspec = (NuSpec) serializer.Deserialize(reader);
+ }
+ var nudeps = nuspec.Metadata.Dependencies;
+ var deps = new List();
+ foreach (var nudep in nudeps)
+ {
+ var dep = new Dependency();
+ dep.Id = nudep.Id;
+
+ var parts = nudep.Version.Split(',');
+ if (parts.Length == 1)
+ {
+ dep.MinInclude = parts[0].StartsWith("[");
+ dep.MaxInclude = parts[0].EndsWith("]");
+
+ SemVersion version;
+ if (!SemVersion.TryParse(parts[0].Substring(1, parts[0].Length-2).Trim(), out version)) continue;
+ dep.MinVersion = dep.MaxVersion = version; //parts[0].Substring(1, parts[0].Length-2).Trim();
+ }
+ else
+ {
+ SemVersion version;
+ if (!SemVersion.TryParse(parts[0].Substring(1).Trim(), out version)) continue;
+ dep.MinVersion = version; //parts[0].Substring(1).Trim();
+ if (!SemVersion.TryParse(parts[1].Substring(0, parts[1].Length-1).Trim(), out version)) continue;
+ dep.MaxVersion = version; //parts[1].Substring(0, parts[1].Length-1).Trim();
+ dep.MinInclude = parts[0].StartsWith("[");
+ dep.MaxInclude = parts[1].EndsWith("]");
+ }
+
+ deps.Add(dep);
+ }
+ return deps.ToArray();
+ }
+
+ public static IEnumerable DistinctBy(/*this*/ IEnumerable source, Func keySelector)
+ {
+ HashSet knownKeys = new HashSet();
+ foreach (TSource element in source)
+ {
+ if (knownKeys.Add(keySelector(element)))
+ {
+ yield return element;
+ }
+ }
+ }
+
+ public static Package[] GetProjectsPackages(string src, string[] projects)
+ {
+ var l = new List();
+ foreach (var project in projects)
+ {
+ var path = Path.Combine(src, project);
+ var packageConfig = Path.Combine(path, "packages.config");
+ if (File.Exists(packageConfig))
+ ReadPackagesConfig(packageConfig, l);
+ var csprojs = Directory.GetFiles(path, "*.csproj");
+ foreach (var csproj in csprojs)
+ {
+ ReadCsProj(csproj, l);
+ }
+ }
+ IEnumerable p = l.OrderBy(x => x.Id);
+ p = DistinctBy(p, x => x.Id + ":::" + x.Version);
+ return p.ToArray();
+ }
+
+ public static object[] GetPackageErrors(Package[] pkgs)
+ {
+ return pkgs
+ .GroupBy(x => x.Id)
+ .Where(x => x.Count() > 1)
+ .ToArray();
+ }
+
+ public static object[] GetNuSpecErrors(Package[] pkgs, Dependency[] deps)
+ {
+ var d = pkgs.ToDictionary(x => x.Id, x => x.Version);
+ return deps
+ .Select(x =>
+ {
+ SemVersion v;
+ if (!d.TryGetValue(x.Id, out v)) return null;
+
+ var ok = true;
+
+ /*
+ if (x.MinInclude)
+ {
+ if (v < x.MinVersion) ok = false;
+ }
+ else
+ {
+ if (v <= x.MinVersion) ok = false;
+ }
+
+ if (x.MaxInclude)
+ {
+ if (v > x.MaxVersion) ok = false;
+ }
+ else
+ {
+ if (v >= x.MaxVersion) ok = false;
+ }
+ */
+
+ if (!x.MinInclude || v != x.MinVersion) ok = false;
+
+ return ok ? null : new { Dependency = x, Version = v };
+ })
+ .Where(x => x != null)
+ .ToArray();
+ }
+
+ /*
+ public static Package[] GetProjectPackages(string path)
+ {
+ var l = new List();
+ var packageConfig = Path.Combine(path, "packages.config");
+ if (File.Exists(packageConfig))
+ ReadPackagesConfig(packageConfig, l);
+ var csprojs = Directory.GetFiles(path, "*.csproj");
+ foreach (var csproj in csprojs)
+ {
+ ReadCsProj(csproj, l);
+ }
+ return l.ToArray();
+ }
+ */
+
+ public static string GetDirectoryName(string filename)
+ {
+ return Path.GetFileName(Path.GetDirectoryName(filename));
+ }
+
+ public static void ReadPackagesConfig(string filename, List packages)
+ {
+ //Console.WriteLine("read " + filename);
+
+ PackagesConfigPackages pkgs;
+ var serializer = new XmlSerializer(typeof(PackagesConfigPackages));
+ using (var reader = new StreamReader(filename))
+ {
+ pkgs = (PackagesConfigPackages) serializer.Deserialize(reader);
+ }
+ foreach (var p in pkgs.Packages)
+ {
+ SemVersion version;
+ if (!SemVersion.TryParse(p.Version, out version)) continue;
+ packages.Add(new Package { Id = p.Id, Version = version, Project = GetDirectoryName(filename) });
+ }
+ }
+
+ public static void ReadCsProj(string filename, List packages)
+ {
+ //Console.WriteLine("read " + filename);
+
+ // if xmlns then it's not a VS2017 with PackageReference
+ var text = File.ReadAllLines(filename);
+ var line = text.FirstOrDefault(x => x.Contains(" x.Packages != null).SelectMany(x => x.Packages))
+ {
+ var sversion = p.VersionE ?? p.VersionA;
+ SemVersion version;
+ if (!SemVersion.TryParse(sversion, out version)) continue;
+ packages.Add(new Package { Id = p.Id, Version = version, Project = GetDirectoryName(filename) });
+ }
+ }
+
+ public class Dependency
+ {
+ public string Id { get; set; }
+ public SemVersion MinVersion { get; set; }
+ public SemVersion MaxVersion { get; set; }
+ public bool MinInclude { get; set; }
+ public bool MaxInclude { get; set; }
+ }
+
+ public class Package
+ {
+ public string Id { get; set; }
+ public SemVersion Version { get; set; }
+ public string Project { get; set; }
+ }
+
+ [XmlType(AnonymousType = true, Namespace = "http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd")]
+ [XmlRoot(Namespace = "http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd", IsNullable = false, ElementName = "package")]
+ public class NuSpec
+ {
+ [XmlElement("metadata")]
+ public NuSpecMetadata Metadata { get; set; }
+ }
+
+ [XmlType(AnonymousType = true, Namespace = "http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd", TypeName = "metadata")]
+ public class NuSpecMetadata
+ {
+ [XmlArray("dependencies")]
+ [XmlArrayItem("dependency", IsNullable = false)]
+ public NuSpecDependency[] Dependencies { get; set; }
+ }
+
+ [XmlType(AnonymousType = true, Namespace = "http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd", TypeName = "dependencies")]
+ public class NuSpecDependency
+ {
+ [XmlAttribute(AttributeName = "id")]
+ public string Id { get; set; }
+
+ [XmlAttribute(AttributeName = "version")]
+ public string Version { get; set; }
+ }
+
+ [XmlType(AnonymousType = true)]
+ [XmlRoot(Namespace = "", IsNullable = false, ElementName = "packages")]
+ public class PackagesConfigPackages
+ {
+ [XmlElement("package")]
+ public PackagesConfigPackage[] Packages { get; set; }
+ }
+
+ [XmlType(AnonymousType = true, TypeName = "package")]
+ public class PackagesConfigPackage
+ {
+ [XmlAttribute(AttributeName = "id")]
+ public string Id { get; set; }
+
+ [XmlAttribute(AttributeName = "version")]
+ public string Version { get; set; }
+ }
+
+ [XmlType(AnonymousType = true)]
+ [XmlRoot(Namespace = "", IsNullable = false, ElementName = "Project")]
+ public class CsProjProject
+ {
+ [XmlElement("ItemGroup")]
+ public CsProjItemGroup[] ItemGroups { get; set; }
+ }
+
+ [XmlType(AnonymousType = true, TypeName = "ItemGroup")]
+ public class CsProjItemGroup
+ {
+ [XmlElement("PackageReference")]
+ public CsProjPackageReference[] Packages { get; set; }
+ }
+
+ [XmlType(AnonymousType = true, TypeName = "PackageReference")]
+ public class CsProjPackageReference
+ {
+ [XmlAttribute(AttributeName = "Include")]
+ public string Id { get; set; }
+
+ [XmlAttribute(AttributeName = "Version")]
+ public string VersionA { get; set; }
+
+ [XmlElement("Version")]
+ public string VersionE { get; set;}
+ }
+ }
+ }
+
+"@
+
+ Write-Host ">> Verify NuGet consistency"
+
+ $assem = (
+ "System.Xml",
+ "System.Core", # "System.Collections.Generic"
+ "System.Linq",
+ "System.Xml.Serialization",
+ "System.IO",
+ "System.Globalization",
+ $uenv.Semver
+ )
+
+ try
+ {
+ # as long as the code hasn't changed it's fine to re-add, but if the code
+ # has changed this will throw - better warn the dev that we have an issue
+ add-type -referencedAssemblies $assem -typeDefinition $source -language CSharp
+ }
+ catch
+ {
+ if ($_.FullyQualifiedErrorId.StartsWith("TYPE_ALREADY_EXISTS,"))
+ { Write-Error "Failed to add type, did you change the code?" }
+ else
+ { Write-Error $_ }
+ }
+ if (-not $?) { break }
+
+ $nuspecs = (
+ "UmbracoCms",
+ "UmbracoCms.Core"
+ )
+
+ $projects = (
+ "Umbraco.Core",
+ "Umbraco.Web",
+ "Umbraco.Web.UI",
+ "UmbracoExamine"#,
+ #"Umbraco.Tests",
+ #"Umbraco.Tests.Benchmarks"
+ )
+
+ $src = "$($uenv.SolutionRoot)\src"
+ $pkgs = [Umbraco.Build.NuGet]::GetProjectsPackages($src, $projects)
+ if (-not $?) { break }
+ #Write-Package "All" $pkgs
+
+ $errs = [Umbraco.Build.NuGet]::GetPackageErrors($pkgs)
+ if (-not $?) { break }
+
+ if ($errs.Length -gt 0)
+ {
+ Write-Host ""
+ }
+ foreach ($err in $errs)
+ {
+ Write-Host $err.Key
+ foreach ($e in $err)
+ {
+ Write-Host " $($e.Version) required by $($e.Project)"
+ }
+ }
+ if ($errs.Length -gt 0)
+ {
+ Write-Error "Found non-consolidated package dependencies"
+ break
+ }
+
+ $nuerr = $false
+ $nupath = "$($uenv.SolutionRoot)\build\NuSpecs"
+ foreach ($nuspec in $nuspecs)
+ {
+ $deps = [Umbraco.Build.NuGet]::GetNuSpecDependencies("$nupath\$nuspec.nuspec")
+ if (-not $?) { break }
+ #Write-NuSpec $nuspec $deps
+
+ $errs = [Umbraco.Build.NuGet]::GetNuSpecErrors($pkgs, $deps)
+ if (-not $?) { break }
+
+ if ($errs.Length -gt 0)
+ {
+ Write-Host ""
+ Write-Host "$nuspec requires:"
+ $nuerr = $true
+ }
+ foreach ($err in $errs)
+ {
+ $m = Format-Dependency $err.Dependency
+ Write-Host " $m but projects require $($err.Version)"
+ }
+ }
+
+ if ($nuerr)
+ {
+ Write-Error "Found inconsistent NuGet dependencies"
+ break
+ }
+}
\ No newline at end of file
diff --git a/build/NuSpecs/UmbracoCms.Core.nuspec b/build/NuSpecs/UmbracoCms.Core.nuspec
index 901742de8d93..1b0e082aa871 100644
--- a/build/NuSpecs/UmbracoCms.Core.nuspec
+++ b/build/NuSpecs/UmbracoCms.Core.nuspec
@@ -1,6 +1,6 @@
-
+
UmbracoCms.Core
7.0.0
Umbraco Cms Core Binaries
@@ -14,93 +14,94 @@
Contains the core assemblies needed to run Umbraco Cms
en-US
umbraco
-
+
+
+
-
-
-
+
+
+
+
-
+
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
diff --git a/build/NuSpecs/UmbracoCms.nuspec b/build/NuSpecs/UmbracoCms.nuspec
index 1cf12b78355e..d3ab992a2332 100644
--- a/build/NuSpecs/UmbracoCms.nuspec
+++ b/build/NuSpecs/UmbracoCms.nuspec
@@ -1,6 +1,6 @@
-
+
UmbracoCms
7.0.0
Umbraco Cms
@@ -16,24 +16,26 @@
umbraco
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/NuSpecs/tools/ReadmeUpgrade.txt b/build/NuSpecs/tools/ReadmeUpgrade.txt
index e0d660a79555..2b6da733a123 100644
--- a/build/NuSpecs/tools/ReadmeUpgrade.txt
+++ b/build/NuSpecs/tools/ReadmeUpgrade.txt
@@ -8,9 +8,17 @@
----------------------------------------------------
-Don't forget to build!
+*** IMPORTANT NOTICE FOR UPGRADES FROM VERSIONS BELOW 7.7.0 ***
+
+Be sure to read the version specific upgrade information before proceeding:
+https://our.umbraco.org/documentation/Getting-Started/Setup/Upgrading/version-specific#version-7-7-0
+
+Depending on the version you are upgrading from, you may need to make some changes to your web.config
+and you will need to be aware of the breaking changes listed there to see if these affect your installation.
+Don't forget to build!
+
We've done our best to transform your configuration files but in case something is not quite right: remember we
backed up your files in App_Data\NuGetBackup so you can find the original files before they were transformed.
diff --git a/build/NuSpecs/tools/Web.config.install.xdt b/build/NuSpecs/tools/Web.config.install.xdt
index cbb60bb94916..5ee5ed32c6d3 100644
--- a/build/NuSpecs/tools/Web.config.install.xdt
+++ b/build/NuSpecs/tools/Web.config.install.xdt
@@ -15,6 +15,7 @@
+
@@ -23,6 +24,7 @@
+
@@ -30,6 +32,7 @@
+
@@ -58,7 +61,7 @@
-
+
>
@@ -330,6 +333,9 @@
+
+
+
@@ -337,7 +343,7 @@
-
+
@@ -349,7 +355,7 @@
-
+
@@ -365,24 +371,32 @@
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
diff --git a/build/NuSpecs/tools/install.core.ps1 b/build/NuSpecs/tools/install.core.ps1
index e2230e0c3237..c53b2cd7e585 100644
--- a/build/NuSpecs/tools/install.core.ps1
+++ b/build/NuSpecs/tools/install.core.ps1
@@ -53,7 +53,6 @@ if ($project) {
if(Test-Path $umbracoBinFolder\umbraco.providers.dll) { Remove-Item $umbracoBinFolder\umbraco.providers.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\Umbraco.Web.UI.dll) { Remove-Item $umbracoBinFolder\Umbraco.Web.UI.dll -Force -Confirm:$false }
if(Test-Path $umbracoBinFolder\UmbracoExamine.dll) { Remove-Item $umbracoBinFolder\UmbracoExamine.dll -Force -Confirm:$false }
- if(Test-Path $umbracoBinFolder\UrlRewritingNet.UrlRewriter.dll) { Remove-Item $umbracoBinFolder\UrlRewritingNet.UrlRewriter.dll -Force -Confirm:$false }
# Delete files Umbraco depends upon
$amd64Folder = Join-Path $umbracoBinFolder "amd64"
diff --git a/build/NuSpecs/tools/install.ps1 b/build/NuSpecs/tools/install.ps1
index 0e62fb0749cf..592dc951e01c 100644
--- a/build/NuSpecs/tools/install.ps1
+++ b/build/NuSpecs/tools/install.ps1
@@ -98,10 +98,51 @@ if ($project) {
$umbracoUIXMLDestination = Join-Path $projectPath "Umbraco\Config\Create\UI.xml"
Copy-Item $umbracoUIXMLSource $umbracoUIXMLDestination -Force
} else {
+ # This part only runs for upgrades
+
$upgradeViewSource = Join-Path $umbracoFolderSource "Views\install\*"
$upgradeView = Join-Path $umbracoFolder "Views\install\"
Write-Host "Copying2 ${upgradeViewSource} to ${upgradeView}"
Copy-Item $upgradeViewSource $upgradeView -Force
+
+ Try
+ {
+ # Disable tours for upgrades, presumably Umbraco experience is already available
+ $umbracoSettingsConfigPath = Join-Path $configFolder "umbracoSettings.config"
+ $content = (Get-Content $umbracoSettingsConfigPath).Replace('','')
+ # Saves with UTF-8 encoding without BOM which makes sure Umbraco can still read it
+ # Reference: https://stackoverflow.com/a/32951824/5018
+ [IO.File]::WriteAllLines($umbracoSettingsConfigPath, $content)
+ }
+ Catch
+ {
+ # Not a big problem if this fails, let it go
+ }
+
+ Try
+ {
+ $uiXmlConfigPath = Join-Path $umbracoFolder -ChildPath "Config" | Join-Path -ChildPath "create" | Join-Path -ChildPath "UI.xml"
+ $uiXmlFile = Join-Path $umbracoFolder -ChildPath "Config" | Join-Path -ChildPath "create" | Join-Path -ChildPath "UI.xml"
+
+ $uiXml = New-Object System.Xml.XmlDocument
+ $uiXml.PreserveWhitespace = $true
+
+ $uiXml.Load($uiXmlFile)
+ $createExists = $uiXml.SelectNodes("//nodeType[@alias='macros']/tasks/create")
+
+ if($createExists.Count -eq 0)
+ {
+ $macrosTasksNode = $uiXml.SelectNodes("//nodeType[@alias='macros']/tasks")
+
+ #Creating:
+ $createNode = $uiXml.CreateElement("create")
+ $createNode.SetAttribute("assembly", "umbraco")
+ $createNode.SetAttribute("type", "macroTasks")
+ $macrosTasksNode.AppendChild($createNode)
+ $uiXml.Save($uiXmlFile)
+ }
+ }
+ Catch { }
}
$installFolder = Join-Path $projectPath "Install"
diff --git a/build/NuSpecs/tools/trees.config.install.xdt b/build/NuSpecs/tools/trees.config.install.xdt
index a9fbf07762cb..5a549e3fd87d 100644
--- a/build/NuSpecs/tools/trees.config.install.xdt
+++ b/build/NuSpecs/tools/trees.config.install.xdt
@@ -34,11 +34,16 @@
xdt:Transform="SetAttributes()" />
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
+
+ xdt:Transform="Remove" />
+
+
\ No newline at end of file
diff --git a/build/ReplaceIISExpressPortNumber.exe b/build/ReplaceIISExpressPortNumber.exe
deleted file mode 100644
index 04334ebffef9..000000000000
Binary files a/build/ReplaceIISExpressPortNumber.exe and /dev/null differ
diff --git a/build/UmbracoVersion.txt b/build/UmbracoVersion.txt
deleted file mode 100644
index 2ff5e180293d..000000000000
--- a/build/UmbracoVersion.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
-7.5.11
\ No newline at end of file
diff --git a/build/azuregalleryrelease.ps1 b/build/azuregalleryrelease.ps1
new file mode 100644
index 000000000000..502ca3010e52
--- /dev/null
+++ b/build/azuregalleryrelease.ps1
@@ -0,0 +1,59 @@
+Param(
+ [string]$GitHubPersonalAccessToken,
+ [string]$Directory
+)
+$workingDirectory = $Directory
+CD $workingDirectory
+
+# Clone repo
+$fullGitUrl = "https://$env:GIT_URL/$env:GIT_REPOSITORYNAME.git"
+git clone $fullGitUrl 2>&1 | % { $_.ToString() }
+
+# Remove everything so that unzipping the release later will update everything
+# Don't remove the readme file nor the git directory
+Write-Host "Cleaning up git directory before adding new version"
+Remove-Item -Recurse $workingDirectory\$env:GIT_REPOSITORYNAME\* -Exclude README.md,.git
+
+# Find release zip
+$zipsDir = "$workingDirectory\$env:BUILD_DEFINITIONNAME\zips"
+$pattern = "UmbracoCms.([0-9]{1,2}.[0-9]{1,3}.[0-9]{1,3}).zip"
+Write-Host "Searching for Umbraco release files in $workingDirectory\$zipsDir for a file with pattern $pattern"
+$file = (Get-ChildItem $zipsDir | Where-Object { $_.Name -match "$pattern" })
+
+if($file)
+{
+ # Get release name
+ $version = [regex]::Match($file.Name, $pattern).captures.groups[1].value
+ $releaseName = "Umbraco $version"
+ Write-Host "Found $releaseName"
+
+ # Unzip into repository to update release
+ Add-Type -AssemblyName System.IO.Compression.FileSystem
+ Write-Host "Unzipping $($file.FullName) to $workingDirectory\$env:GIT_REPOSITORYNAME"
+ [System.IO.Compression.ZipFile]::ExtractToDirectory("$($file.FullName)", "$workingDirectory\$env:GIT_REPOSITORYNAME")
+
+ # Telling git who we are
+ git config --global user.email "coffee@umbraco.com" 2>&1 | % { $_.ToString() }
+ git config --global user.name "Umbraco HQ" 2>&1 | % { $_.ToString() }
+
+ # Commit
+ CD $env:GIT_REPOSITORYNAME
+ Write-Host "Committing Umbraco $version Release from Build Output"
+
+ git add . 2>&1 | % { $_.ToString() }
+ git commit -m " Release $releaseName from Build Output" 2>&1 | % { $_.ToString() }
+
+ # Tag the release
+ git tag -a "v$version" -m "v$version"
+
+ # Push release to master
+ $fullGitAuthUrl = "https://$($env:GIT_USERNAME):$GitHubPersonalAccessToken@$env:GIT_URL/$env:GIT_REPOSITORYNAME.git"
+ git push $fullGitAuthUrl 2>&1 | % { $_.ToString() }
+
+ #Push tag to master
+ git push $fullGitAuthUrl --tags 2>&1 | % { $_.ToString() }
+}
+else
+{
+ Write-Error "Umbraco release file not found, searched in $workingDirectory\$zipsDir for a file with pattern $pattern - cancelling"
+}
diff --git a/build/build.ps1 b/build/build.ps1
new file mode 100644
index 000000000000..72d8287d9c5a
--- /dev/null
+++ b/build/build.ps1
@@ -0,0 +1,67 @@
+param (
+ [Parameter(Mandatory=$false)]
+ [string]
+ $version,
+
+ [Parameter(Mandatory=$false)]
+ [Alias("mo")]
+ [switch]
+ $moduleOnly = $false
+)
+
+# the script can run either from the solution root,
+# or from the ./build directory - anything else fails
+if ([System.IO.Path]::GetFileName($pwd) -eq "build")
+{
+ $mpath = [System.IO.Path]::GetDirectoryName($pwd) + "\build\Modules\"
+}
+else
+{
+ $mpath = "$pwd\build\Modules\"
+}
+
+# look for the module and throw if not found
+if (-not [System.IO.Directory]::Exists($mpath + "Umbraco.Build"))
+{
+ Write-Error "Could not locate Umbraco build Powershell module."
+ break
+}
+
+# add the module path (if not already there)
+if (-not $env:PSModulePath.Contains($mpath))
+{
+ $env:PSModulePath = "$mpath;$env:PSModulePath"
+}
+
+# force-import (or re-import) the module
+Write-Host "Import Umbraco build Powershell module"
+Import-Module Umbraco.Build -Force -DisableNameChecking
+
+# module only?
+if ($moduleOnly)
+{
+ if (-not [string]::IsNullOrWhiteSpace($version))
+ {
+ Write-Host "(module only: ignoring version parameter)"
+ }
+ else
+ {
+ Write-Host "(module only)"
+ }
+ break
+}
+
+# get build environment
+Write-Host "Setup Umbraco build Environment"
+$uenv = Get-UmbracoBuildEnv
+
+# set the version if any
+if (-not [string]::IsNullOrWhiteSpace($version))
+{
+ Write-Host "Set Umbraco version to $version"
+ Set-UmbracoVersion $version
+}
+
+# full umbraco build
+Write-Host "Build Umbraco"
+Build-Umbraco
\ No newline at end of file
diff --git a/build/setversion.ps1 b/build/setversion.ps1
new file mode 100644
index 000000000000..99f1534bf55d
--- /dev/null
+++ b/build/setversion.ps1
@@ -0,0 +1,18 @@
+# Usage: powershell .\setversion.ps1 7.6.8
+# Or: powershell .\setversion 7.6.8-beta001
+
+param (
+ [Parameter(Mandatory=$true)]
+ [string]
+ $version
+)
+
+# report
+Write-Host "Setting Umbraco version to $version"
+
+# import Umbraco Build PowerShell module - $pwd is ./build
+$env:PSModulePath = "$pwd\Modules\;$env:PSModulePath"
+Import-Module Umbraco.Build -Force -DisableNameChecking
+
+# run commands
+$version = Set-UmbracoVersion -Version $version
\ No newline at end of file
diff --git a/src/.nuget/NuGet.Config b/src/.nuget/NuGet.Config
deleted file mode 100644
index 6a318ad9b75f..000000000000
--- a/src/.nuget/NuGet.Config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/.nuget/NuGet.exe b/src/.nuget/NuGet.exe
deleted file mode 100644
index 9ca66594f912..000000000000
Binary files a/src/.nuget/NuGet.exe and /dev/null differ
diff --git a/src/.nuget/NuGet.targets b/src/.nuget/NuGet.targets
deleted file mode 100644
index 6ff51f6e83c7..000000000000
--- a/src/.nuget/NuGet.targets
+++ /dev/null
@@ -1,138 +0,0 @@
-
-
-
- $(MSBuildProjectDirectory)\..\
-
-
- false
-
-
- false
-
-
- true
-
-
- false
-
-
-
-
-
-
-
-
-
-
-
-
- $([System.IO.Path]::Combine($(SolutionDir), ".nuget"))
- $([System.IO.Path]::Combine($(ProjectDir), "packages.config"))
-
-
-
-
- $(SolutionDir).nuget
- packages.config
-
-
-
-
- $(NuGetToolsPath)\NuGet.exe
- @(PackageSource)
-
- "$(NuGetExePath)"
- mono --runtime=v4.0.30319 $(NuGetExePath)
-
- $(TargetDir.Trim('\\'))
-
- -RequireConsent
- -NonInteractive
-
- "$(SolutionDir) "
- "$(SolutionDir)"
-
-
- $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)
- $(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols
-
-
-
- RestorePackages;
- $(BuildDependsOn);
-
-
-
-
- $(BuildDependsOn);
- BuildPackage;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/NuGet.Config b/src/NuGet.Config
index dcccfdd5c113..89e79db976ac 100644
--- a/src/NuGet.Config
+++ b/src/NuGet.Config
@@ -2,6 +2,6 @@
-
+
\ No newline at end of file
diff --git a/src/SQLCE4Umbraco/SqlCE4Umbraco.csproj b/src/SQLCE4Umbraco/SqlCE4Umbraco.csproj
index 0689a7a7d4e1..454a6cf2ce3a 100644
--- a/src/SQLCE4Umbraco/SqlCE4Umbraco.csproj
+++ b/src/SQLCE4Umbraco/SqlCE4Umbraco.csproj
@@ -1,5 +1,5 @@
-
+
Debug
AnyCPU
@@ -91,7 +91,6 @@
-
signed assemblies)
+ ///
+ public sealed class BindingRedirects
+ {
+ public static void Initialize()
+ {
+ // this only gets called when an assembly can't be resolved
+ AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
+ }
+
+ private static readonly Regex Log4NetAssemblyPattern = new Regex("log4net, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=\\w+$", RegexOptions.Compiled);
+ private const string Log4NetReplacement = "log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a";
+
+ ///
+ /// This is used to do an assembly binding redirect via code - normally required due to signature changes in assemblies
+ ///
+ ///
+ ///
+ ///
+ private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
+ {
+ //log4net:
+ if (Log4NetAssemblyPattern.IsMatch(args.Name) && args.Name != Log4NetReplacement)
+ {
+ return Assembly.Load(Log4NetAssemblyPattern.Replace(args.Name, Log4NetReplacement));
+ }
+
+ //AutoMapper:
+ // ensure the assembly is indeed AutoMapper and that the PublicKeyToken is null before trying to Load again
+ // do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stackoverflow
+ if (args.Name.StartsWith("AutoMapper") && args.Name.EndsWith("PublicKeyToken=null"))
+ return Assembly.Load(args.Name.Replace(", PublicKeyToken=null", ", PublicKeyToken=be96cd2c38ef1005"));
+
+ return null;
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/ByteArrayExtensions.cs b/src/Umbraco.Core/ByteArrayExtensions.cs
new file mode 100644
index 000000000000..dacdd509ca61
--- /dev/null
+++ b/src/Umbraco.Core/ByteArrayExtensions.cs
@@ -0,0 +1,39 @@
+namespace Umbraco.Core
+{
+ public static class ByteArrayExtensions
+ {
+ private static readonly char[] BytesToHexStringLookup = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+ public static string ToHexString(this byte[] bytes)
+ {
+ int i = 0, p = 0, bytesLength = bytes.Length;
+ var chars = new char[bytesLength * 2];
+ while (i < bytesLength)
+ {
+ var b = bytes[i++];
+ chars[p++] = BytesToHexStringLookup[b / 0x10];
+ chars[p++] = BytesToHexStringLookup[b % 0x10];
+ }
+ return new string(chars, 0, chars.Length);
+ }
+
+ public static string ToHexString(this byte[] bytes, char separator, int blockSize, int blockCount)
+ {
+ int p = 0, bytesLength = bytes.Length, count = 0, size = 0;
+ var chars = new char[bytesLength * 2 + blockCount];
+ for (var i = 0; i < bytesLength; i++)
+ {
+ var b = bytes[i++];
+ chars[p++] = BytesToHexStringLookup[b / 0x10];
+ chars[p++] = BytesToHexStringLookup[b % 0x10];
+ if (count == blockCount) continue;
+ if (++size < blockSize) continue;
+
+ chars[p++] = '/';
+ size = 0;
+ count++;
+ }
+ return new string(chars, 0, chars.Length);
+ }
+ }
+}
diff --git a/src/Umbraco.Core/Cache/CacheKeys.cs b/src/Umbraco.Core/Cache/CacheKeys.cs
index 3b9ee9c63a26..c9991ba45a1e 100644
--- a/src/Umbraco.Core/Cache/CacheKeys.cs
+++ b/src/Umbraco.Core/Cache/CacheKeys.cs
@@ -55,8 +55,10 @@ public static class CacheKeys
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
[EditorBrowsable(EditorBrowsableState.Never)]
public const string UserCacheKey = "UmbracoUser";
-
- public const string UserPermissionsCacheKey = "UmbracoUserPermissions";
+
+ [Obsolete("This is no longer used and will be removed from the codebase in the future")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public const string UserGroupPermissionsCacheKey = "UmbracoUserGroupPermissions";
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
public const string ContentTypeCacheKey = "UmbracoContentType";
@@ -89,7 +91,7 @@ public static class CacheKeys
public const string DataTypeCacheKey = "UmbracoDataTypeDefinition";
public const string DataTypePreValuesCacheKey = "UmbracoPreVal";
- public const string IdToKeyCacheKey = "UI2K";
- public const string KeyToIdCacheKey = "UK2I";
+ public const string IdToKeyCacheKey = "UI2K__";
+ public const string KeyToIdCacheKey = "UK2I__";
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Cache/DeepCloneRuntimeCacheProvider.cs b/src/Umbraco.Core/Cache/DeepCloneRuntimeCacheProvider.cs
index 0ae721943d2a..14fef80f0d1e 100644
--- a/src/Umbraco.Core/Cache/DeepCloneRuntimeCacheProvider.cs
+++ b/src/Umbraco.Core/Cache/DeepCloneRuntimeCacheProvider.cs
@@ -26,6 +26,9 @@ internal class DeepCloneRuntimeCacheProvider : IRuntimeCacheProvider, IRuntimeCa
public DeepCloneRuntimeCacheProvider(IRuntimeCacheProvider innerProvider)
{
+ if (innerProvider.GetType() == typeof(DeepCloneRuntimeCacheProvider))
+ throw new InvalidOperationException("A " + typeof(DeepCloneRuntimeCacheProvider) + " cannot wrap another instance of " + typeof(DeepCloneRuntimeCacheProvider));
+
InnerProvider = innerProvider;
}
@@ -105,9 +108,11 @@ public object GetCacheItem(string cacheKey, Func