Initial version of watch target.
- Added FileWatcher helper class - Added ability to disable fetching k from nuget every time it's called - Added watch target to standard goals - Added ability to skip project generation for net45. This is useful for watch so that changes made to the project but not saved to disk won't be discarded when the watcher runs.
This commit is contained in:
parent
37e225d517
commit
1964e884e1
|
|
@ -0,0 +1,122 @@
|
|||
use namespace="System.Collections.Concurrent"
|
||||
|
||||
functions
|
||||
@{
|
||||
public class FileWatcher
|
||||
{
|
||||
private readonly HashSet<string> _files = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly ConcurrentDictionary<string, HashSet<string>> _directories = new ConcurrentDictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private readonly FileSystemWatcher _watcher;
|
||||
|
||||
public FileWatcher(string path)
|
||||
{
|
||||
_watcher = new FileSystemWatcher(path);
|
||||
_watcher.IncludeSubdirectories = true;
|
||||
_watcher.EnableRaisingEvents = true;
|
||||
|
||||
_watcher.Changed += OnWatcherChanged;
|
||||
_watcher.Renamed += OnRenamed;
|
||||
_watcher.Deleted += OnWatcherChanged;
|
||||
_watcher.Created += OnWatcherChanged;
|
||||
}
|
||||
|
||||
public event Action<string> OnChanged;
|
||||
|
||||
public void WatchDirectory(string path, string extension)
|
||||
{
|
||||
var extensions = _directories.GetOrAdd(path, _ => new HashSet<string>(StringComparer.OrdinalIgnoreCase));
|
||||
|
||||
extensions.Add(extension);
|
||||
}
|
||||
|
||||
public bool WatchFile(string path)
|
||||
{
|
||||
return _files.Add(path);
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
_watcher.Dispose();
|
||||
}
|
||||
|
||||
public bool ReportChange(string newPath, WatcherChangeTypes changeType)
|
||||
{
|
||||
return ReportChange(oldPath: null, newPath: newPath, changeType: changeType);
|
||||
}
|
||||
|
||||
public bool ReportChange(string oldPath, string newPath, WatcherChangeTypes changeType)
|
||||
{
|
||||
if (HasChanged(oldPath, newPath, changeType))
|
||||
{
|
||||
if (oldPath != null)
|
||||
{
|
||||
Trace.TraceInformation("{0} -> {1}", oldPath, newPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
Trace.TraceInformation("{0} -> {1}", changeType, newPath);
|
||||
}
|
||||
|
||||
if (OnChanged != null)
|
||||
{
|
||||
OnChanged(newPath);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void OnRenamed(object sender, RenamedEventArgs e)
|
||||
{
|
||||
ReportChange(e.OldFullPath, e.FullPath, e.ChangeType);
|
||||
}
|
||||
|
||||
private void OnWatcherChanged(object sender, FileSystemEventArgs e)
|
||||
{
|
||||
ReportChange(e.FullPath, e.ChangeType);
|
||||
}
|
||||
|
||||
private bool HasChanged(string oldPath, string newPath, WatcherChangeTypes changeType)
|
||||
{
|
||||
// File changes
|
||||
if (_files.Contains(newPath) ||
|
||||
(oldPath != null && _files.Contains(oldPath)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
HashSet<string> extensions;
|
||||
if (_directories.TryGetValue(newPath, out extensions) ||
|
||||
_directories.TryGetValue(Path.GetDirectoryName(newPath), out extensions))
|
||||
{
|
||||
string extension = Path.GetExtension(newPath);
|
||||
|
||||
if (String.IsNullOrEmpty(extension))
|
||||
{
|
||||
// Assume it's a directory
|
||||
if (changeType == WatcherChangeTypes.Created ||
|
||||
changeType == WatcherChangeTypes.Renamed)
|
||||
{
|
||||
foreach (var e in extensions)
|
||||
{
|
||||
WatchDirectory(newPath, e);
|
||||
}
|
||||
}
|
||||
else if(changeType == WatcherChangeTypes.Deleted)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ignore anything else
|
||||
return false;
|
||||
}
|
||||
|
||||
return extensions.Contains(extension);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,11 +17,16 @@ k-generate-projects
|
|||
solutionPath=''
|
||||
Required. Path to the solution directory
|
||||
|
||||
skipNet45='false'
|
||||
Optional. Skip net45 project regeneration
|
||||
|
||||
*/}
|
||||
|
||||
content var='net45' include href='net45.txt'
|
||||
content var='k10' include href='k10.txt'
|
||||
|
||||
default skipNet45='${false}'
|
||||
|
||||
@{
|
||||
ProjectGenerator.Logger = Log;
|
||||
|
||||
|
|
@ -30,6 +35,11 @@ content var='k10' include href='k10.txt'
|
|||
{ "k10", k10 }
|
||||
};
|
||||
|
||||
if(skipNet45)
|
||||
{
|
||||
templates.Remove("net45");
|
||||
}
|
||||
|
||||
ProjectGenerator.MakeProjects(solutionPath, templates);
|
||||
}
|
||||
|
||||
|
|
@ -245,9 +255,17 @@ functions
|
|||
|
||||
foreach (var pair in configs)
|
||||
{
|
||||
var targetFramework = pair.Key;
|
||||
|
||||
string projectTemplate;
|
||||
if(!templates.TryGetValue(targetFramework, out projectTemplate))
|
||||
{
|
||||
Warn("Skipping project generation for " + projectName + " - " + targetFramework);
|
||||
continue;
|
||||
}
|
||||
|
||||
var allPackageReferences = new Dictionary<string, string>(packageReferences);
|
||||
|
||||
var targetFramework = pair.Key;
|
||||
var props = (IDictionary<string, object>)pair.Value;
|
||||
|
||||
var specificCompilationOptions = GetObject(props, "compilationOptions") ?? compilationOptions ?? new Dictionary<string, object>();
|
||||
|
|
@ -294,7 +312,7 @@ functions
|
|||
}
|
||||
}
|
||||
|
||||
var template = templates[targetFramework]
|
||||
var template = projectTemplate
|
||||
.Replace("{ProjectGuid}", id)
|
||||
.Replace("{Name}", projectName)
|
||||
.Replace("{Defines}", String.Join(";", defines))
|
||||
|
|
@ -359,7 +377,7 @@ functions
|
|||
"Microsoft.Net.ApplicationHost.dll");
|
||||
|
||||
var klrSwitches = configType == "k10" ? "--core45" : "--net45";
|
||||
var args = klrSwitches + " " + appHostPath + " " + projectRoot + " --nobin";
|
||||
var args = klrSwitches + " " + appHostPath + " --nobin " + projectRoot;
|
||||
|
||||
return String.Format(@"<StartAction>Program</StartAction>
|
||||
<StartProgram>{0}</StartProgram>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use namespace="System"
|
|||
use namespace="System.IO"
|
||||
use import="Files"
|
||||
use import="BuildEnv"
|
||||
use import="FileWatcher"
|
||||
|
||||
default BASE_DIR='${Directory.GetCurrentDirectory()}'
|
||||
default TARGET_DIR='${Path.Combine(BASE_DIR, "artifacts")}'
|
||||
|
|
@ -34,7 +35,53 @@ default TEST_DIR='${Path.Combine(TARGET_DIR, "test")}'
|
|||
#nuget-install target='install' description='Copy NuGet packages to local repo'
|
||||
nuget-local-publish sourcePackagesDir='${BUILD_DIR}'
|
||||
|
||||
|
||||
#watch
|
||||
@{
|
||||
var watcher = new FileWatcher(BASE_DIR);
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(BASE_DIR, "*.json", SearchOption.AllDirectories))
|
||||
{
|
||||
watcher.WatchFile(file);
|
||||
}
|
||||
|
||||
foreach (var file in Directory.EnumerateFiles(BASE_DIR, "*.cs", SearchOption.AllDirectories))
|
||||
{
|
||||
watcher.WatchFile(file);
|
||||
}
|
||||
|
||||
foreach (var dir in Directory.EnumerateDirectories(BASE_DIR, "*.*", SearchOption.AllDirectories))
|
||||
{
|
||||
watcher.WatchDirectory(dir, ".cs");
|
||||
watcher.WatchDirectory(dir, ".json");
|
||||
}
|
||||
|
||||
watcher.OnChanged += path =>
|
||||
{
|
||||
Log.Info("Change detected in " + path);
|
||||
bool restore = path.EndsWith("project.json");
|
||||
|
||||
try
|
||||
{
|
||||
UpdateProjects(BASE_DIR, restore);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn(ex.Message);
|
||||
}
|
||||
|
||||
Log.Info("Waiting for changes...");
|
||||
};
|
||||
|
||||
Log.Info("Waiting for changes...");
|
||||
Console.ReadLine();
|
||||
}
|
||||
|
||||
functions @{
|
||||
string E(string key) { return Environment.GetEnvironmentVariable(key); }
|
||||
void E(string key, string value) { Environment.SetEnvironmentVariable(key, value); }
|
||||
}
|
||||
|
||||
macro name='UpdateProjects' basePath='string' restore='bool'
|
||||
k command='restore' prefetch='${false}' if='restore'
|
||||
k-generate-projects solutionPath='${basePath}' skipNet45='${!restore}'
|
||||
|
|
@ -11,9 +11,14 @@ kProgram='...'
|
|||
|
||||
command=''
|
||||
|
||||
prefetch='true'
|
||||
May be passed if fetching k from nuget is required before running
|
||||
|
||||
*/}
|
||||
|
||||
nuget-install package='ProjectK' outputDir='packages' extra='-pre' once='ProjectK-NuGet'
|
||||
default prefetch='${true}'
|
||||
|
||||
nuget-install package='ProjectK' outputDir='packages' extra='-pre' once='ProjectK-NuGet' if='prefetch'
|
||||
|
||||
@{
|
||||
Func<string, long> getVersion = version => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue