Mastodon

First Do No Harm

Chef Sugar is a module for the infrastructure automation tool Chef. In September, it came to the attention of the module’s developer that Chef had entered a contract with the United State’s Immigration and Customs Enforcement agency. Citing "a moral and ethical obligation to prevent [his] source from being used for evil", he removed the code from its public repository. While this is not the first time a developer removing a public module has garnered attention, it raises a number of questions for the free software and open source communities, namely, “What should ‘free as in freedom’ actually entail,” and “what can developers actually demand of their users?”

Free Software isn’t Free

One of the Free Software Foundation’s mantras, mentioned earlier, is “free as in freedom,” and as anyone who’s taken an introductory philosophy course in University (*raises hand*) can’t help but mention (aside from the fact that they took Philospohy in University) is that freedom comes in two flavors, positive and negative. As a result of this dichotomy, the notion of absolute freedom is a fallacious one. One individual’s positive freedom to exercise an action can infringe upon another individual’s negative freedom from the consequences of that action being exercised.

On a less abstract level, free software imposes requirements on its users by way of waiving copyright restrictions in accordance with the terms enumerated in its license. The severity of these requirements vary from trivial attribution requests to the viral terms of Copyleft licenses. It is clear that the “freedom” of free software is bounded to some degree.

Ethical Source Software

Ethics in computing is hardly a glamorous topic, a sentiment that only compounds the a priori feelings of apathy towards it. What’s the worst thing that anyone has done with a computer? Invent Facebook? Unlike other professions, such as medicine, computing is seen as benign, and rightly so because it is only ever employed directly in benign tasks. The problem with this perspective however, is that it ignores the nature of computing; that computing is a means to an end, not an end in and of itself.

The most apt illustration of this idea comes from the earliest days of computing, before the advent of the semiconductor, when in 1933 the Deutsche Hollerith Maschinen Gesellschaft, a direct subsidiary of the newly-christened International Business Machines (IBM), began collating census data for the newly-appointed Chancellor of Germany, Adolf Hitler. Their work quadrupled the the number of citizens associated with Jewish heritage at the time, accounting for almost one-third the murders committed in concentration camps by the end of the war.[1]

Today, orders of magnitude more data is being processed with computational power unimaginable almost a century ago, with the aim of identifying persons in the United States without the necessary heritage or legal documents. Though the intent may be dissimilar from that of the leader of the Weimar Republic, the results are not. This is the power of computing: it confers upon the user a multiplicative force that warrants even greater care.

David and Goliath

Now, dear reader, I’m sure you’re thinking, “That’s all fine and good, but I’m just one developer. You honestly expect me to be able to go toe-to-toe against *insert big corporation here*!?” Yes, I do, because others have, and made a mark. Case in point: The much-maligned JSON license, a near-carbon copy of the much-beloved MIT license, with one additional caveat:

The Software shall be used for Good, not Evil.

These nine words ring of origins on Mount Sinai and have caused concern among fellow developers and lawyers alike, with users (in a twist directed by M. Night Shamalan) such as IBM, asking for special licensing. Listening to the JSON licenses’ creator, Douglas Crockford, speak about it gives one the sense that its inception wasn’t exactly driven by serious ethical concerns regarding the use of JSON, however it does demonstrate that licensing does matter and can be a powerful tool if wielded properly.

A Hippocratic Corpus for the Rest of Us*

One of the biggest criticisms of the JSON license, that I must agree with, is that the wording is ambiguous at best. Assuming that you and I would like to contribute to a cause greater than mere trolling, we will need a license with a little more substantive language. Enter, the Hippocratic License, created by Coraline Ada Ehmk, of Contributer Covenant fame (yes, the one that broke the Linux Kernel Group). Written in the spirit of the oath sworn by doctors for millennia with 0% of the problematic wording of the original (seriously, go read it, it’s great!), the Hippocratic license embodies the (one hopes) same spirit of the JSON license while deriving its language from international law.

It is truly incredible that individuals are taking a stand for what they believe in ways that go beyond slack-tivism. While changing the terms by which others can use some code you wrote and put on the Internet probably won’t prevent future genocide, we’ve shown that it can help hinder efforts by those who wish to amplify their effectiveness with such tools, albeit indirectly, and if nothing else, sends a message that such actions are not tolerated.

If you have code you wrote and put up on the Internet like I do, please consider updating your licenses, and whether or not you distribute code publicly, consider contributing to further the important work of putting the power of computing to the use of making the world a better place for all of us (and come on, you’re already giving $5 per month to that podcast about Apple computers and magic tricks).

* Nailed it.

References

  1. Black, Edwin (2009). IBM and the Holocaust: The Strategic Alliance Between Nazi Germany and America’s Most Powerful Corporation (Paperback) (Second ed.). Washington, DC: Dialog Press. OCLC 958727212.
❋❋❋

An rsync Crash Course

Whether you’re a beginner Bash scripter or seasoned sysadmin, rsync is an indispensable tool for efficient file transfer and synchronization. It’s easy to use, yet incredibly powerful, and beguiles many a script kiddie and cargo-cult programmer alike, myself included at times. While I do encourage everyone to #ReadTheDocs and open man rsync, it’s less of a page and more of a novella, so let’s take a bird’s-eye view and look at some of the more useful options, and practical examples of their application.

Usage overview

$
rsync [option(s)] [source(s)] [destination]

Like most commands, rsync has a fairly straight-forward signature: Options follow the executable name, then a list of sources to send, with their destination at the end.

Options

  • -a, —archive, same as -rlptgoD, recursively sync source directory while preserving all attributes except hard links

  • -D , same as —devices —specials, syncs system files used to represent connected devices and special files such as shortcuts, and sockets and pipes related to inter-process communication.[1]

  • —delete, delete all files in the destination not present in the source

  • -e, —rsh=COMMAND, specify the remote shell to use

  • -g, —group, preserve group

  • -h, —human-readable, —progress

  • -l, —links, copy symlinks

  • —safe-links, ignore symlinks that point outside the directory from being copied

  • -n, --dry-run

  • -o, —owner, preserve owner

  • -p, —perms, preserve permissions

  • -r, —recursive, recurse into directories in source

  • -t, —times, preserve times

  • -u, —update, skip files with a newer timestamp at the destination

  • -v, —verbose, increase output verbosity

  • -z, —compress, compress file data during the transfer

  • —include=PATTERN, only sync files matching the given pattern

  • —exclude=PATTERN, skip files matching the given pattern

  • —include-from=FILE, read inclusion pattern from given file

  • —exclude-from=FILE, read exclusion pattern from given file

  • —files-from=FILE, read list of source-file names from given file

Sync local directories

$
rsync -avz —delete /src/directory/ /dest/directory

Note that the trailing / on a source directory indicates to copy its contents rather than the directory itself.

Sync remote directories

$
rsync -avz -e ssh /src/directory/ user@host:/dest/directory

macOS

When sending the contents of a volume from its root on macOS, save yourself some cycles and remember to exclude a few volume-specific hidden directories.[2]

$
... —-exclude={ '.fseventsd', '.Spotlight-V100', '.Trashes' }

Permissions and owners and timestamps, oh my!

For most use cases, the --archive flag works perfectly well, but not all. One such case is sending files to a directory with a different owner, for example /var/www on a web server. One probably wouldn’t want to preserve ownership or group of the files being sent in that case, and would want to simply use just -r instead of -a.

Conclusion

rsync is a powerful yet easy to use file transfer and synchronization utility that has a spot in every developer’s tool belt. While it is just as easy to misuse at times, having an understanding of its most common use cases will help guide you through the documentation and navigate those edge cases where --archive isn’t quite the answer.

Additional Resources

References

  1. What is the -D switch in rsync? - Ask Ubuntu

  2. Rsync cheatsheet

❋❋❋

Storing Metadata in Core Data

Persistence frameworks for iOS seem to go from 0 to 100 real quick. Need to store a few booleans and maybe a string? UserDefaults will do just fine! How about a few tens of model instances? Well, you could either serialize it to a plist, à la UserDefaults, or here’s an entire object graph and persistence framework backed by an SQL data store and oh by the way, it’s one of the most complex Cocoa frameworks and it’s called Core Data! Don’t get me wrong, I really warmed up to Core Data after I found out how difficult it is to serialize a tree with just Swift’s Codable protocol, however defining full-blown entities for certain trivial data makes about as much sense as a nuclear hand grenade, especially when that data is metadata related to our Core Data store, such as the timestamp of the last update or the latest commit ID. Keeping this data in a store alongside the user’s preferred theme or units of measurement feels wrong, as it fragments our model layer. Luckily, Core Data comes with a baked-in solution in the form of the metadata dictionary. Each NSPersistentStore object contains a metadata property which can be read from with the NSPersistentStoreCoordinator instance method metadata(for:).

func lastUpdatedOn(_ persistentContainer: NSPersistentContainer) -> Date? {
let coordinator = persistentContainer.persistentStoreCoordinator
guard let store = coordinator.persistentStores.first else {
fatalError("Unable to retrieve persistent store")
}
let metadata = coordinator.metadata(for: store)
guard let lastUpdated: Date = metadata["lastUpdated"] as? Date else {
return nil
}
return lastUpdated
}

Note, if you’re using NSPersistentContainer, you can spare yourself the optional chaining and access your persistent store through it instead of through an NSManagedObjectContext instance.

To write metadata, use the setMetadata(_:for:) method on your store’s NSPersistentStoreCoordinator.

let coordinator = persistentContainer.persistentStoreCoordinator
guard let store = coordinator.persistentStores.first else {
fatalError("Unable to retrieve persistent store")
}
coordinator.setMetadata(["lastUpdated": lastUpdated], for: store)

After writing metadata, you’ll need to save the managed object context referring to the store’s coordinator. One possible Good Enough™ solution is to perform the metadata updates and saves in a completion handler after any transactions.

func fetchUpdates(completion: { context in
guard let coordinator = context.persistentStoreCoordinator else {
fatalError("Unable to retrieve persistent store coordinator")
}
guard let store = coordinator.persistentStores.first else {
fatalError("Unable to retrieve persistent store")
}
coordinator.setMetadata(["lastUpdated": Date.now()], for: store)
context.save()
})

An added bonus of using Core Data metadata over other persistence methods is that because it is a property of NSPersistentStore, it follows its associated data wherever the store goes! This is particularly useful if you ever need to seed or move a persistent store.

Additional Resources