git rev-list --reverse HEAD -- words.csv | \ xargs -I {} sh -c 'echo $(git show -s --date=short --format="%ad" {}) $(git show {}:./words.csv | wc -l)'
Nathan Baulch
Sunday, October 6, 2024
Extract line count of file at each git revision
Wednesday, February 16, 2022
Traverse into zip files when walking the file system
func WalkDirZip(fsys fs.FS, root string, fn WalkDirFunc) error { return fs.WalkDir(fsys, root, func(path string, d fs.DirEntry, err error) error { if d.IsDir() || !strings.EqualFold(filepath.Ext(path), ".zip") { return fn(fsys, path, d, err) } else if f, err := fsys.Open(path); err != nil { return err } else if s, err := f.Stat(); err != nil { return err } else if zfs, err := zip.NewReader(f.(io.ReaderAt), s.Size()); err != nil { return err } else { return fs.WalkDir(zfs, ".", func(path string, d fs.DirEntry, err error) error { return fn(zfs, path, d, err) }) } }) } type WalkDirFunc func(fsys fs.FS, path string, d fs.DirEntry, err error) error
Friday, December 13, 2019
Recursively compact git repositories within a directory
find -name .git -exec echo {} \; -execdir git gc --aggressive ";"
Thursday, October 6, 2016
Generic extension method for traversing object graphs
- public static IEnumerable
Traverse (this T root, Func > getChildren) { return Enumerable.Repeat(root, 1) .Concat((getChildren(root) ?? Enumerable.Empty ()) .SelectMany(child => Traverse(child, getChildren))); }
Tuesday, August 23, 2016
Extract attachments and inline files from a MIME message
MimeKit
- MimeMessage msg;
- using (var stream = File.OpenRead(fileName))
- {
- msg = MimeMessage.Load(stream);
- }
- foreach (var part in msg.BodyParts.OfType
().Where(part => !string.IsNullOrEmpty(part.FileName))) { using (var stream = File.OpenWrite(Path.Combine(Path.GetDirectoryName(fileName), part.FileName))) { part.ContentObject.DecodeTo(stream); } }
Tuesday, April 8, 2014
Deserialize an anonymous type using SimpleJson
SimpleJson
- var json = "{\"name\": \"Joe\"," +
- "\"age\": 25," +
- "\"address\": {\"city\": \"Paris\"}," +
- "\"emails\": [\"joe@home.com\", \"joe@work.com\"]," +
- "\"phones\": [{\"type\": \"Mobile\", \"number\": \"555 1234\"}]}";
- var prototype = new
- {
- name = default(string),
- age = default(int),
- address = new {city = default(string)},
- emails = new string[0],
- phones = new[] {new {type = default(string), number = default(string)}}
- };
- var result = SimpleJsonExt.DeserializeAnonymousObject(json, prototype);
- using CacheEntry = KeyValuePair<ParameterInfo[], ReflectionUtils.ConstructorDelegate>;
- public static class SimpleJsonExt
- {
- public static T DeserializeAnonymousObject<T>(string json, T prototype)
- {
- return SimpleJson.SimpleJson.DeserializeObject<T>(json, new Strategy());
- }
- private class Strategy : PocoJsonSerializerStrategy
- {
- private readonly IDictionary<Type, CacheEntry> _ctorCache =
- new ReflectionUtils.ThreadSafeDictionary<Type, CacheEntry>(CreateConstructorDelegate);
- private static CacheEntry CreateConstructorDelegate(Type key)
- {
- var ctors = key.GetConstructors();
- if (ctors.Length == 1)
- {
- var ctor = ctors[0];
- var parms = ctor.GetParameters();
- if (parms.Length > 0)
- {
- return new CacheEntry(parms, ReflectionUtils.GetContructor(ctor));
- }
- }
- return default(CacheEntry);
- }
- public override object DeserializeObject(object value, Type type)
- {
- var dict = value as IDictionary<string, object>;
- if (dict != null)
- {
- var ctor = _ctorCache[type];
- if (ctor.Key != null)
- {
- return ctor.Value(ctor.Key
- .Select(param => DeserializeObject(
- dict.TryGetValue(param.Name, out value) ? value : null,
- param.ParameterType))
- .ToArray());
- }
- }
- return base.DeserializeObject(value, type);
- }
- }
- }
Sunday, November 24, 2013
Recursively search and replace files from one folder into another
- $filter = '*.dll', '*.pdb'
- $copied = 0; $skipped = 0; $failed = 0
- $sourceFiles = $filter | % { Get-ChildItem $sourceDir -Filter $_ -Recurse } `
- | sort @{expression={$_.FullName.Length}} -Descending `
- | group Name -AsHashTable
- $targetFiles = $filter | % { Get-ChildItem $targetDir -Filter $_ -Recurse } `
- | ? { $sourceFiles.ContainsKey($_.Name) } `
- | sort FullName
- $targetFiles | % {
- $target = $_
- $sourceFiles[$target.Name] | % {
- $source = $_
- if ($target.FullName.EndsWith($source.FullName.Substring($sourceDir.Length),
- 'InvariantCultureIgnoreCase')) {
- if ($target.LastWriteTime.AddSeconds(2) -lt $source.LastWriteTime) {
- Write-Host $target.FullName
- try {
- Copy-Item $source.FullName $target.FullName -Force
- $copied++
- }
- catch {
- Write-Error $_.Message
- $failed++
- }
- }
- else {
- $skipped++
- }
- return
- }
- }
- }
- Write-Host "$copied copied, $skipped skipped, $failed failed in $($watch.Elapsed)"
Thursday, March 14, 2013
Programmatically configure a simple log4net trace appender
log4net
- var hierarchy = (Hierarchy) LogManager.GetRepository();
- var logger = (Logger) hierarchy.GetLogger(loggerName);
- logger.Level = Level.Debug;
- logger.AddAppender(new TraceAppender {Layout = new SimpleLayout()});
- hierarchy.Configured = true;
Monday, January 28, 2013
Convert an SQL like pattern into a regular expression pattern
- var pattern = Regex.Replace(
- likePattern,
- @"[%_]|\[[^]]*\]|[^%_[]+",
- match =>
- {
- if (match.Value == "%")
- {
- return ".*";
- }
- if (match.Value == "_")
- {
- return ".";
- }
- if (match.Value.StartsWith("[") && match.Value.EndsWith("]"))
- {
- return match.Value;
- }
- return Regex.Escape(match.Value);
- });
Saturday, January 12, 2013
Load test a web site using asynchronous requests and the TPL
Task Parallel Library (TPL)
- var queue = new Queue<Task>();
- while (true)
- {
- if (queue.Count >= 50)
- {
- var task = queue.Dequeue();
- task.Wait();
- task.Dispose();
- }
- var request = (HttpWebRequest) WebRequest.Create(url);
- var watch = Stopwatch.StartNew();
- queue.Enqueue(Task.Factory
- .FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null)
- .ContinueWith(task =>
- {
- using (var response = (HttpWebResponse) task.Result)
- {
- Console.WriteLine("{0}\t{1}\t{2}",
- response.StatusCode, response.ContentType, watch.Elapsed);
- }
- }));
- }
Thursday, June 28, 2012
Calculate the exponential moving average of a stream of numbers
- public static IEnumerable<double> ExponentialMovingAverage(this IEnumerable<double> source, double alpha)
- {
- double? last = null;
- return source.Select(
- value =>
- {
- var average = last != null ? alpha*value + (1 - alpha)*last.Value : value;
- last = average;
- return average;
- });
- }
Thursday, February 16, 2012
Create a fast compiled method invoker using LINQ
- var method = new Func<double, double, double>(Math.Pow).Method;
- var parameter = Expression.Parameter(typeof(object[]));
- var args = method.GetParameters()
- .Select((param, i) => Expression.Convert(
- Expression.ArrayIndex(parameter, Expression.Constant(i)), param.ParameterType));
- var expr = Expression.Lambda<Func<object[], object>>(
- Expression.Convert(Expression.Call(method, args), typeof(object)), parameter);
- var invoker = expr.Compile();
- var result = invoker(new object[] {Math.PI, 2.0});
Friday, February 10, 2012
Create a Google calendar event in an existing calendar
Google Data API .NET client library
- var credentials = new GDataCredentials(userName, password);
- var service = new CalendarService(null) {Credentials = credentials};
- var query = new CalendarQuery("https://www.google.com/calendar/feeds/default/owncalendars/full");
- var feed = service.Query(query);
- var eventFeedLink = feed.Entries.Cast<CalendarEntry>()
- .Where(item => item.Title.Text == calendarName)
- .SelectMany(item => item.Links)
- .First(link => link.Rel == GDataParserNameTable.NSGCal + "#eventFeed");
- var entry = new EventEntry(title) {Times = {new When(start, end, allDay)}};
- service.Insert(new Uri(eventFeedLink.AbsoluteUri), entry);
Thursday, February 2, 2012
Page through potentially large NHibernate criteria query results
NHibernate
- public static IEnumerable<T> Enumerate<T>(this ICriteria criteria, int pageSize = 1000)
- {
- var entityCount = CriteriaTransformer.TransformToRowCount(criteria).UniqueResult<int>();
- var pageCount = (int) Math.Ceiling(entityCount/(double) pageSize);
- criteria = CriteriaTransformer.Clone(criteria).SetMaxResults(pageSize);
- return Enumerable.Range(0, pageCount)
- .SelectMany(pageNum => criteria.SetFirstResult(pageNum*pageSize).List<T>());
- }
Friday, January 20, 2012
Create a YouTube playlist containing all the uploads of a given user
Google Data API .NET client library
- var credentials = new GDataCredentials(userName, password);
- var service = new YouTubeService(applicationName, developerKey) {Credentials = credentials};
- var entry = new AtomEntry {Title = {Text = playlistName}};
- entry = service.Insert(new Uri(YouTubeQuery.CreatePlaylistsUri(null)), entry);
- var id = ((XmlExtension) entry.FindExtension("playlistId", YouTubeNameTable.NSYouTube)).Node.InnerText;
- var batchUri = new Uri(string.Format("https://gdata.youtube.com/feeds/api/playlists/{0}/batch", id));
- var query = new YouTubeQuery(YouTubeQuery.CreateUserUri(sourceUser)) {StartIndex = 1};
- AtomFeed feed;
- do
- {
- feed = service.Query(query);
- service.Batch(feed, batchUri);
- query.StartIndex += feed.Entries.Count;
- } while (query.StartIndex < feed.TotalResults);
Sunday, January 8, 2012
List the users of a TFS project associated with a local workspace path
- var workspace = Workstation.Current.GetLocalWorkspaceInfo(path);
- var tfs = new TfsTeamProjectCollection(workspace.ServerUri);
- var gss = tfs.GetService<IGroupSecurityService>();
- var grp = gss.ReadIdentity(SearchFactor.EveryoneApplicationGroup, null, QueryMembership.Expanded);
- var names = gss.ReadIdentities(SearchFactor.Sid, grp.Members, QueryMembership.None)
- .Where(identity => identity.Type == IdentityType.WindowsUser)
- .Select(identity => string.Format(@"{0}\{1}", identity.Domain, identity.AccountName))
- .ToArray();
Friday, January 6, 2012
Quartz scheduler job that re-triggers itself on completion
Quartz.NET
- public class RetriggerJob : IInterruptableJob
- {
- private bool _interrupted;
- public void Execute(IJobExecutionContext context)
- {
- Thread.Sleep(1000);
- if (_interrupted)
- {
- return;
- }
- context.Scheduler.TriggerJob(context.JobDetail.Key);
- if (_interrupted)
- {
- context.Scheduler.Interrupt(context.JobDetail.Key);
- }
- }
- public void Interrupt()
- {
- _interrupted = true;
- }
- }
Friday, December 30, 2011
Read a published Google spreadsheet into a DataTable using GData
Google Data API .NET client library
- var service = new SpreadsheetsService(null);
- var query = new ListQuery("0AjD5UGMt5CGDdEcwaS10S2IzVzJFNDYtaEo5anN2RHc", "1", "public", "values");
- var feed = service.Query(query);
- var table = new DataTable();
- foreach (ListEntry entry in feed.Entries)
- {
- var row = table.NewRow();
- foreach (ListEntry.Custom element in entry.Elements)
- {
- var column = table.Columns[element.LocalName] ??
- table.Columns.Add(element.LocalName);
- row[column] = element.Value;
- }
- table.Rows.Add(row);
- }
Saturday, December 17, 2011
Determine if a WinForms control resource file is localized
- XPathDocument doc;
- using (var stream = File.OpenRead(fileName))
- {
- doc = new XPathDocument(stream);
- }
- var nav = doc.CreateNavigator();
- var itr = nav.Select("root/data[@name = '>>$this.Name']");
- var localized = itr.Count > 0;
Remove matching C# region directives using LINQ
- var flag = false;
- var modified = false;
- var lines = File.ReadLines(fileName)
- .Where(line =>
- {
- if ((!flag && line.Contains("#region " + regionName)) ||
- (flag && line.Contains("#endregion")))
- {
- flag = !flag;
- modified = true;
- return false;
- }
- return true;
- })
- .ToArray();
- if (modified)
- {
- File.WriteAllLines(fileName, lines);
- }
Thursday, December 8, 2011
Compile and execute a stateful T4 template using Mono.TextTemplating
Mono.TextTemplating
- var input =
- "<#@ template language=\"C#\" debug=\"true\" #>" +
- "<#+ static int num; #>" +
- "<#= num++ #>";
- var generator = new TemplateGenerator();
- var compiled = generator.CompileTemplate(input);
- Debug.Assert(Equals(compiled.Process(), "0"));
- Debug.Assert(Equals(compiled.Process(), "1"));
- Debug.Assert(Equals(compiled.Process(), "2"));
Subscribe to:
Posts (Atom)