Fixing an issue with output parameters that are of type IntPtr
[castle.git] / Experiments / SubversionHooks / pre-commit / Application.cs
blob92d3a77c2231fbb2989882f248a60278a1058708
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.SvnHooks
17 using System;
18 using System.Collections;
19 using System.Configuration;
20 using System.Diagnostics;
21 using System.Text.RegularExpressions;
23 using Castle.MicroKernel;
24 using Castle.Windsor;
25 using Castle.Windsor.Configuration.Interpreters;
26 using Castle.Windsor.Configuration.Sources;
28 using Castle.SvnHooks;
30 /// <summary>
31 /// Summary description for Application.
32 /// </summary>
33 public class Application
36 private static bool HooksAllow(RepositoryFile file, IPreCommit[] hooks)
38 bool hooksOK = true;
39 foreach (IPreCommit hook in hooks)
41 Error[] errors = hook.PreCommit(file);
42 if(errors != null && errors.Length > 0)
44 hooksOK = false;
45 Console.Error.WriteLine("An error occured in \"{0}\"", file);
46 foreach(Error error in errors)
48 Console.Error.WriteLine(error.Description);
53 return hooksOK;
56 private static IPreCommit[] FetchHooks(IKernel kernel)
58 ArrayList list = new ArrayList();
59 foreach (IHandler handler in kernel.GetHandlers(typeof(IPreCommit)))
61 IPreCommit hook = (IPreCommit)handler.Resolve();
62 list.Add(hook);
65 return (IPreCommit[])list.ToArray(typeof(IPreCommit));
68 /// <summary>
69 /// The main entry point for the application.
70 /// </summary>
71 [STAThread]
72 static int Main(string[] args)
74 try
76 // Fetch paths and transaction from configuration and arguments
77 String svnlookPath = ConfigurationSettings.AppSettings["svnlook.location"];
78 String repositoryPath = args[0];
79 String transactionString = args[1];
80 Transaction transaction = Transaction.Parse(transactionString);
82 // Initialize a WindsorContainer with all the relevant hooks
83 // and repository.
84 WindsorContainer container = new WindsorContainer(new XmlInterpreter(new AppDomainConfigSource("castle")));
85 IRepository repository = new DefaultRepository(
86 svnlookPath,
87 repositoryPath,
88 transaction);
90 container.Kernel.AddComponentInstance("Repository", typeof(IRepository), repository);
92 // Fetch all the hooks from the container, if we get none
93 // we dont need to process the files in the transaction
94 // and can simply exit the program with success at this point.
95 IPreCommit[] hooks = FetchHooks(container.Kernel);
97 if (hooks.Length == 0)
98 return 0;
100 // Start processing all the files commited and run the hooks
101 // on them. This is done by executing a changed command on
102 // svnlook and parsing the result for the files/directories.
103 bool hooksOK = true;
104 Regex lineRegex = new Regex("^(?<contents>[AUD_])(?<properties>[U ]) +(?<file>[^ ].*) *$");
105 SvnLook svnLook = new SvnLook(svnlookPath, repositoryPath);
106 using(Process process = svnLook.Execute(SvnLookCommand.Changed, transaction, null))
108 String line;
109 while((line = process.StandardOutput.ReadLine()) != null)
111 Match m = lineRegex.Match(line);
113 if(!m.Success)
115 Console.Error.WriteLine("Could not match line: " + line);
116 return 3;
119 if(m.Groups["file"].Value.EndsWith("/"))
121 // This is a directory, not a file.
123 // TODO: Add directory handling
125 else
127 RepositoryStatus contentsStatus;
128 RepositoryStatus propertiesStatus;
130 switch (m.Groups["contents"].Value)
132 case "A":
133 contentsStatus = RepositoryStatus.Added;
134 break;
135 case "U":
136 contentsStatus = RepositoryStatus.Updated;
137 break;
138 case "D":
139 contentsStatus = RepositoryStatus.Deleted;
140 break;
141 case "_":
142 contentsStatus = RepositoryStatus.Unchanged;
143 break;
144 default:
145 Console.Error.WriteLine("Could not match status flags for contents on line: " + line);
146 return 3;
148 switch (m.Groups["properties"].Value)
150 case "U":
151 propertiesStatus = RepositoryStatus.Updated;
152 break;
153 case " ":
154 propertiesStatus = RepositoryStatus.Unchanged;
155 break;
156 default:
157 Console.Error.WriteLine("Could not match status flags for properties on line: " + line);
158 return 3;
161 using(RepositoryFile file = new RepositoryFile(repository, m.Groups["file"].Value, contentsStatus, propertiesStatus))
164 // If HooksAllow returns false we should not allow
165 // the transaction, but rather than exiting we store
166 // that fact in a boolean so that the user will be
167 // told all errors his files contain rather than just
168 // one at a time.
170 hooksOK &= HooksAllow(file, hooks);
178 if (!hooksOK)
179 return 1;
183 return 0;
185 catch(Exception e)
187 Console.Error.WriteLine("An uncaught exception was thrown in the hook implementation");
188 Console.Error.WriteLine(e.Message);
189 return 2;