chipx86
The company began to grow fast in the years after I joined. VMware's early culture was amazing (a template for any company, imho), but it's hard to maintain that with fast growth. Not a unique situation, but I feel it had an impact on how we addressed certain challenges.
ESX was big, and we wanted to figure out the next big thing. There were a few initiatives, some gambles. Reorgs didn't always match and some initiatives got starved, others over-fed.
Let me take the opportunity to say that we did have a lot of freedom in engineering to build and experiment, which I always loved. This was a strength of the company. Personally, I got to figure out and build Unity in our Workstation product (it let you pop windws out of a VM into the host -- SUPER challenging), the whole remote VM infrastructure for Workstation (took 3 years with a major rewrite), WSX (early-days HTML5 client for accessing VMs using just a native browser and a network connection), amongst others.
But the world changed and we didn't really nail this. Case in point, The Cloud. (And later Docker.)
In early Cloud days, we were trying to figure out what that all this really should look like, how we fit in. We had things in the works that didn't get released or got restarted, we had some really useful bits that got spun out. What we should have built was more obvious in retrospect, but not so much at the time.
I think we had a lot of really good people in the management chain, and overall people were trying to do the right things there. But we did have a few high-impact bone-headed decisions (some short-term cost savings at the expense of longer-term strategy in parts of some departments) and some people who shouldn't have had the responsibilities they did (in my opinion). Some of these decisions may have made sense at those levels at the time due to factors they were dealing with that I don't know about, but these did damage.
Bear in mind, it was a big company in a quickly-evolving industry, and it's not always easy to get things right. I would NOT say "corporate greed" or "screwing over customers" or anything like that. Not while I was there. But missteps and hard questions to answer about the future.
All that said, I enjoyed working there. I left to work on Review Board (https://www.reviewboard.org) full time in 2013, and then my old team disbanded in 2016, but much of the team still gets dinner every month, 10 years later. Still sees movies, still hangs out in a Discord. I wouldn't trade working there for anything.
I agree with your point about "winning was the default state." I joined during the Diane Greene era and left in the Pat Gelsinger era, spoke to all three CEOs at different points in one-on-ones, and learned a lot about how different people approach the challenges of running a company and listening to employees.
Pre-Broadcom, sort of toward the end of my time there, there was a lot of unintended self-sabotage that didn't need to happen. We lost people that we shouldn't and shot ourselves in the foot for some really dumb reasons, which just a bit more coordination could have prevented. There were some innovative ideas that got lost in all this, and I believe could have fueled VMware's product line and put it in the right positions for where the sector ultimately went. Alas.
Based on this work, there's now a new suite of tools for producing games under the Faxanadu engine, new major mods built with all this, and some work on a modified ROM better built for porting and modding.
Disassembly is here: https://chipx86.com/faxanadu/
And I've been blogging about it at https://chipx86.blog/
Building a universal web-based retro game modding tool along with that work called Nostalgia Studio. The idea is that there's a core foundation for representing game state and building editors, a platform-specific layer for representing things like the NES APU and PPU state, and then game-specific implementations that populate state for two layers below.
Those are the hobbies.
Day job, I work on Review Board (https://www.reviewboard.org), one of the original code review products. We just released Review Board 8, which was a pretty large project (we built Office document review, browser-native spell checking in CodeMirror, a new interdiff filtering algorithm, Forgejo integration, and a bunch of other things).
So now I'm working on plans for Review Board 9, with a goal of releasing within the next 4-6 months. Got some thoughts on how the review process can be rethought for this current era of development, so starting work on that.
https://github.com/icitry?tab=repositories
And he has a YouTube channel linked to his GitHub. Here's his video on the development of this project:
https://www.youtube.com/watch?v=qzpZQe7JT-o
Maybe AI was involved, maybe it wasn't. I don't know. But the author seems to know what he's doing, rather than someone just giving Claude a task and posting the result to GitHub. He talks through some of the challenges in building this, some of the different implementations he tried, the kinds of bugs and crashes he hit, and ultimately what worked and what didn't.
This is exactly the kind of stuff I love. Another comment said Claude has killed interest in crazy projects, but for me, as someone who likes to hand-craft some "why would you even think of that?" projects from time to time, discovering his repositories and YouTube has made my day.
Thanks for posting this, MBCook :)
Very happy still with the Backbone way of building webapps.
if() isn't the only way to do this, though. We've been using a technique in Review Board that's roughly equivalent to if(), but compatible with any browser supporting CSS variables. It involves:
1. Defining your conditions based on selectors/media queries (say, a dark mode media selector, light mode, some data attribute on a component, etc.).
2. Defining a set of related CSS variables within those to mark which are TRUE (using an empty value) and which are FALSE (`initial`).
3. Using those CSS variables with fallback syntax to choose a value based on which is TRUE (using `var(--my-state, fallback)` syntax).
I wrote about it all here, with a handful of working examples: https://chipx86.blog/2025/08/08/what-if-using-conditional-cs...
Also includes a comparison between if() and this approach, so you can more easily get a sense of how they both work.
Got a good family story about that whole acquisition attempt, but I don't want to speak publicly on behalf of my uncle. I know we've talked at length about the what-ifs of that moment.
I do have a scattering of some neat Quarterdeck memorabilia I can share, though:
https://www.dropbox.com/scl/fo/0ca1omn2kwda9op5go34e/ACpO6bz...
I should have mentioned originally (and I've since updated my post) that this and the kw_only= flag both require Python 3.10 and higher, so code that works with older versions can't opt into it yet.
All the kw_only=True argument for dataclasses does is require that you pass any fields you want to provide as keyword arguments instead of positional arguments when instantiating a dataclass. So:
obj = MyDataclass(a=1, b=2, c=3)
Instead of: obj = MyDataclass(1, 2, 3) # This would be an error with kw_only=True
The problem you're describing in boto3 (and a lot of other API bindings, and a lot of more layered Python code) is that methods often take in **kwargs and pass them down to a common function that's handling them. From the caller's perspective, **kwargs is a black box with no details on what's in there. Without a docstring or an understanding of the call chain, it's not helpful.Python sort of has a fix for this now, which is to use a TypedDict to define all the possible values in the **kwargs, like so:
from typing import TypedDict, Unpack
class MyFuncKwargs(TypedDict):
arg1: str
arg2: str
arg3: int | None
def my_outer_func(
**kwargs: Unpack[MyFuncKwargs],
) -> None:
_my_inner_func(**kwargs)
def _my_inner_func(
*,
arg1: str,
arg2: str,
arg3: int | None,
) -> None:
...
By defining a TypedDict and typing **kwargs, the IDE and docs can do a better job of showing what arguments the function really takes, and validating them.Also useful when the function is just a wrapper around serializing **kwargs to JSON for an API, or something.
But this feature is far from free to use. The more functions you have, the more of these you need to create and maintain.
Ideally, a function could type **kwargs as something like:
def my_outer_func(
**kwargs: KwargsOf[_my_inner_func],
) -> None:
...
And then the IDEs and other tooling can just reference that function. This would help make the problem go away for many of the cases where **kwargs is used and passed around.What we do is go through a deprecation phase. Our process is:
* We provide compatibility with the old signature for 2 major releases.
* We document the change and the timeline clearly in the docstring.
* The function gets decorated with a helper that checks the call, and if any keyword-only arguments are provided as positional, it warns and converts them to keyword-only.
* After 2 major releases, we move fully to the new signature.
We buit a Python library called housekeeping (https://github.com/beanbaginc/housekeeping) to help with this. One of the things it contains is a decorator called `@deprecate_non_keyword_only_args`, which takes a deprecation warning class and a function using the signature we're moving to. That decorator handles the check logic and generates a suitable, consistent deprecation message.
That normally looks like:
@deprecate_non_keyword_only_args(MyDeprecationWarning)
def my_func(*, a, b, c):
...
But this is a bit more tricky with dataclasses, since `__init__()` is generated automatically. Fortunately, it can be patched after the fact. A bit less clean, but doable.So here's how we'd handle this case with dataclasses:
from dataclasses import dataclass
from housekeeping import BaseRemovedInWarning, deprecate_non_keyword_only_args
class RemovedInMyProject20Warning(BaseRemovedInWarning):
product = 'MyProject'
version = '2.0'
@dataclass(kw_only=True)
class MyDataclass:
a: int
b: int
c: str
MyDataclass.__init__ = deprecate_non_keyword_only_args(
RemovedInMyProject20Warning
)(MyDataclass.__init__)
Call it with some positional arguments: dc = MyDataclass(1, 2, c='hi')
and you'd get: testdataclass.py:26: RemovedInMyProject20Warning: Positional arguments `a`, `b` must be passed as keyword arguments when calling `__main__.MyDataclass.__init__()`. Passing as positional arguments will be required in MyProject 2.0.
dc = MyDataclass(1, 2, c='hi')
We'll probably add explicit dataclass support to this soon, since we're starting to move to kw_only=True for dataclasses.It'd have been amazing having something like DiffX when we started building some of these SCM integrations too. It's really saved us a lot of trouble with some of the recent ones we've built (PlasticSCM / Unity Version Control, Keysight SOS, and ClearCase), which didn't have a format to work with and needed a lot of extra metadata for lookups and some other stuff.
It's been a few years now, and so far so good for the purposes we built it for. And it's there for any other tool or SCM authors to use if it also happens to be useful to them.
1. There are two important areas where encoding can matter: The filename and the diff content.
Git pays attention to filename encoding, but most SCMs don't, so when a diff is generated, it's based on the local encoding. If there are any non-ASCII characters in that filename, a diff generated in one environment with one encoding set can end up not applying to another (or, in our case, not being able to be looked up from a repository). This isn't common but it can happen (we've seen this on Perforce and Subversion).
Then there's the content. Many SCMs will actually give you a representation of a text file and not the raw contents itself. That text file will be re-encoded for your local/preferred encoding, and newlines may be adjusted as well (`\r\n`, `\n`). The text file is then re-encoded back when pushing the change. This allows people in different environments to operate on the same file regardless of what encoding they're working with.
This doesn't necessarily make its way into the diff, though. So when you send a diff from a less-common encoding to a tool to process it, and that tries to apply it to the file checked out with its encoding, it can fail to patch.
The solution is to either know the encoding of the file you're processing, or try to guess it (some tools, like ours, let you specify a list of preferred encodings to try).
It's best if you can know it up-front.
Bonus Fun Fact: On some SCMs (Perforce comes to mind), checking out a file on Windows and then diffing it Linux via a shared mount can get you a diff with `\r\r\n` newlines. It's a bad time and breaks patching. And it used to come up a lot, until we worked around it.
Also, Perforce for a while would sometimes normalize encodings incorrectly and you'd end up with BOMs in the diff, breaking GNU patch.
2. It does when you're working with them directly for applying and patching. If you're handing them off to a tool for processing, if there's any risk of one file in a sequence not being included, you can end up with breakages that maybe you don't see until later processing.
It's also just really nice having all the state and metadata up-front so we can process it in one go in a consistent way without having to sanity-check all the diffs against each other.
When working locally, it also depends on your tooling. `git format-patch` and `git am` are great, but are for Git. If I'm working with (let's just say) Subversion, I need to do my own thing or find another tool.
3. It's critical for the kind of information needed to locate files in a repository. Some systems need a commit-wide identifier. Some need per-file identifiers. Some need a combination of the two. Some need those plus additional data not otherwise represented in the path or revision (generally more enterprise SCMs targeting certain use cases).
It's also critical for representing information that isn't in the Unified Diff format (namely, anything but the filename). So, symlink information, file modes, SCM-specific properties on a file or directory, to name a few. This information needs to live somewhere if a SCM provides it, and it's up to every SCM to choose how and where to store that data (and then how it's encoded, etc.).
I have so many stories I could tell at this point.
When talking about the file, the two terms are often used interchangeably (and are usually a .diff or a .patch extension).
For fun, the GNU Patch manpage says:
"NAME: patch - apply a diff file to an original"
followed by:
"patch takes a patch file patchfile containing ..."
"patch tries to skip any leading garbage, apply the diff, and then ..."
These aren't problems end users should hopefully ever need to worry about, but they're problems that tools need to worry about and work around. Especially for SCMs that don't have a diff format of their own, have one that is missing data (in some, not all changes can be represented, e.g. deleted files), or don't include enough information for another tool to identify the file in a repository.
This isn't a tool for viewing changes to files or to ASTs. This is a way of being able to generate a single diff file for processing or patching that addresses the kinds of problems we've encountered in over 20 years of building diff parsing tooling and working with over a dozen SCMs with varying levels of completeness or brokenness of bespoke custom diff formats.
It's not an end user tool, but a useful format for tools like code review products to use.
Other SCMs can and do use a Git-style diff format, but as there's no defined grammar, there are sometimes important differences. For example, Mercurial's Git-style diffs represent the revisions in a different format than Git's does with different meanings, reuse Git "index" lines for binary files but include SHAs of the file contents instead of any sort of revision, and have a header block that should be stripped out before sending to a Git-style diff parser.
The header formats are meant to be very simple key/value pairs that are known by the parser, and not free-form bits of metadata. That's what the "meta" blocks are for. The parsing rules for the header are intentionally very simple.
JSON was chosen after a lot of discussion between us and outside parties and after experimentation with other grammars. The header for a meta block can specify a format used to serialize the data, in case down the road something supplants JSON in a meaningful way. We didn't want to box ourselves in, but we also don't want to just let any format sit in there (as that brings us back to the format compatibility headaches we face today).
For the other notes:
1. Compatibility is a key factor here, so we'd want to go with base-level JSON. I'd prefer being able to have trailing commas in lists, but not enough to make life hard for someone implementing this without access to a JSON5 parser.
2. If your goal is to simply feed to GNU patch (or similar), you can still split it. This extra data is in the Unified Diff "garbage" areas, so they'll be ignored anyway (so long as they don't conflict, and we take care to ensure that in our recommendations on encoding).
If your goal is to split into two DiffX files, it does become more complicated in that you'd need to re-add the leading headers.
That said, not all diff formats used in the wild can be split and still retain all metadata. Mercurial diffs, for example, have a header that must be present at the top to indicate parent commit information. You can remove that and still feed to GNU patch, but Mercurial (or tools supporting the format) will no longer have the information on the parent commit.
3. Revisions depend heavily on the SCM. Some SCMs use a commit identifier. Some use per-file identifiers. Some use a combination of the two. Some use those plus additional information that either gets injected into the diff or needs to be known out-of-bounds. There's a wide variety of requirements here across the SCM landscape.
The intent here isn't to let you copy changes from one type of repository to another, but to have a format that can be generated from many SCMs that a tool could parse in a consistent way.
Right now, tools working with diffs from multiple types of SCMs need at least one diff parser per SCM (some provide multiple formats, or have significantly changed compatibility between releases.
For SCMs that lack a diff format (there are several) or lack one that contains enough information to identify a file or its changes (there are several), tools also need to choose a method to represent that information. That often means yet another custom diff format that is specific to the tool consuming the diff.
We've spent over 20 years dealing with the headaches and pain points here, giving it a lot of thought. DiffX (which is now a few years old itself) has worked out very well as a solution for us. This wasn't done in a vacuum, but rather has gone through many rounds of discussion with developers at a few different SCM vendors who have given thought to these issues and supplied much valuable feedback and improvements for the spec.
This format is meant to be an extension of Unified Diffs (much like the diff formats of most SCMs), and not something entirely new and focusing on other areas. But if more specific diff formats become widespread, we could directly support encoding them within DiffX as well, as we do for binary diffs formats.
There's not one patch/diff format. There's often at least one per SCM. A couple are pretty good (Git's), many are okay (Subversion's), and many are really bad or non-existent.
I founded one of the older code review products, Review Board (turning 20 next year), and we deal with the problems this is trying to solve all the time, across over a dozen SCMs. So we're the ones complaining :) And much of this is based on extensive feedback from SCM vendors we've spoken to about this at length.
Most people shouldn't have to care. But it benefits tools like ours that have to deal with the nightmare that is the world of diff formats.
Diff files are there to represent a delta state of the repository, a difference between a range of changes. Those may be one or more commits, or one more changes across individual files (not all SCMs manage state in terms of atomic commits). File changes, file attribute changes, SCM-specific metadata changes, and commit history information.
That delta state should be able to be applied to another tree in order to get the same end result. This is what diff files are ultimately there for.
Git diffs do this today, and they do it well (but they're pretty Git-specific). Many SCMs (and there are a lot of them) don't include a format on that level, or a format at all. Hence DiffX.
Having the whole state of a series of commits up-front can help with tools like ours that need that information ideally in one place and need to do analysis across multiple commits.
We also wanted to avoid issues where, due to a bug or network error or whatever, a missing patch in a sequence could result in a broken set of changes to apply. This is obvious when you're patching locally, but less so when you're sending to a tool to process later. Having it up-front reduces the chances of problems and simplifies a lot of edge cases.
Git's diff format contains enough information to do this, but many don't. When this happens, tools like ours (a code review platform) is forced to modify the diff format or otherwise attach information to do these sorts of operations.
We've had to do this enough times, and work around enough inconsistencies and breakages in various SCM-specific diff format variants that we decided to address the problem head-on, pulling our experiences and those of some of the SCM vendors we work with to draft a solution to the problem.
We needed something for ourselves at the very least. Much of DiffX came from thinking about these pain points and from talking to other SCM vendors whose engineers have also given some thought to these problems.
There are a lot of alternative approaches to how one might generate a diff (see VCDIFF for binary files), and much that's worth thinking about for generating diff-like formats that are not line-based. But this is not meant to be those. It is meant to be able to incorporate those as time goes on (as it does with VCDIFF today).
Key point: Much of this is about solving issues with tools that work with the varying file formats of diffs. It's not really something end users should ever have to care about.