Developer Workflow for shared Modules

Topics: Customizing Orchard, Writing modules, Writing themes
Oct 17, 2011 at 2:53 PM

We are using Orchard for several projects. As part of this work we have created modules that need to be shared across each of these projects. However, we haven’t found a great way of sharing these modules between projects. We need the source code of the shared modules to be available in the Visual Studio solution for all projects, but don’t want copies in each of the projects source control repositories.

 

To allow us to do this we have created a repository for our core modules (we are using Subversion) and then pulled those modules in using svn externals. So our core modules are pulled into another folder alongside the “Modules” folder called “External”. However, to make this work we have had to make a change to the Orchard source to look for modules in this “External” folder as well as “Modules”. This works okay, but we would prefer if we didn’t need to change the source code.

 

Another way this could work is if Orchard looked in recursive folders under the “Modules” directory, rather than just the first level of folders.

 

Is there a better workflow for this kind of thing?

Coordinator
Oct 17, 2011 at 6:40 PM

We do subrepositories for recent modules (check out 1.3 modules for that).

Oct 25, 2011 at 11:24 AM

Not sure where I can find the subrepositories you are talking about. I've looked through the 1.3.9 release and haven't found anything relating to subrepositories. Can you clarify?

DownChapel, any chance you could post or share the source code you modified to allow to pull in modules from the External folder? I was planning on doing something pretty much exactly the same as that so if you can post it I'd appreciate it! 

thanks

 

Coordinator
Oct 25, 2011 at 6:14 PM

Example of a subrepo: src/orchard.web/modules/orchard.rules.

Oct 26, 2011 at 2:07 PM
Edited Oct 26, 2011 at 2:08 PM

You can see the subrepositories in this commit http://orchard.codeplex.com/SourceControl/changeset/view/1c3ba112913c#.hgsub

 

We've gone back to using externals in much the same way the Orchard team are using subrepositories because we didn't want to have to patch the source. However, if you want the code, details are below.

I created a class called ExternalExtensions:

 

namespace Orchard.Environment.Extensions
{
    public static class ExternalExtensions {
        private static List<string> _paths;

        public static List<string> GetPaths() {
            return _paths ?? (_paths = GetExternalExtensionPaths());
        }

        private static List<string> GetExternalExtensionPaths() {
            var externalModulesFolder = HostingEnvironment.MapPath("~/External");

            if (string.IsNullOrEmpty(externalModulesFolder) || !Directory.Exists(externalModulesFolder))
                return new List<string>();

            var directoryInfo = new DirectoryInfo(externalModulesFolder);
            return directoryInfo.EnumerateDirectories().Select(d => "~/External/" + d.Name).ToList();
        }
    }
}

 

Then updated two Orchard classes to use this: OrchardStarter.cs and RazorViewEngineProvider.cs:

 

OrchardStarter.cs

Added GetModulePaths method, called from where the ModuleFolders class is registered in Autofac:
	
builder.RegisterType<ModuleFolders>().As<IExtensionFolders>().SingleInstance()
                                .WithParameter(new NamedParameter("paths", GetModulePaths()));
	private static string[] GetModulePaths()
	{
		var modulePaths = new List<string> {"~/Modules"}; // include Orchard built in modules folder.

		modulePaths.AddRange(ExternalExtensions.GetPaths());

		return modulePaths.ToArray();
	}

 

RazorViewEngineProvider

Added GetExternalModulePaths method, called from the CreateModulesViewEngine method:

	public  IViewEngine CreateModulesViewEngine(CreateModulesViewEngineParams parameters) {
            var areaFormatsList = new List<string>(GetExternalModulePaths());
            areaFormatsList.Add("~/Core/{2}/Views/{1}/{0}.cshtml");

 

...
	private static IEnumerable<string> GetExternalModulePaths()
        {
            return ExternalExtensions.GetPaths().Select(d => d + "/{2}/Views/{1}/{0}.cshtml").ToArray();
        }

 

Note, the dynamic compilation seemed to not work for these modules, so I presume there is another change that needs to be made to get that to work. 


Thanks

Oct 28, 2011 at 7:42 AM

Great. Thanks.