Git: handling an appcache?
Asked Answered
D

3

15

I'm hosting an OSS project on GitHub that has a few different developers. This project is a web application that is using an AppCache to tell the browser which files should be made available offline.

It's the nature of the appcache file that it needs to be updated (e.g. we are using a timestamp in a comment for that) once a file in the cache is changing to invalidate the cache and to force the browser to reload all files.
When people are working now on different development branches they are updating the timestamp in the appcache with each of their commits.

The problem is now, that this will create conflicts that are preventing an automatic merge.

  • How can this be solved in a way that not conflicts will happen again in the future?
  • What are other development teams doing at the same situation?

Using CVS I could replace the timestamp with a $Id$ to let the program handle it automatically...

Dramatist answered 26/4, 2015 at 16:49 Comment(1)
The question is generic and should also be answered generic. But for information: in my case the application uses only static JavaScript, CSS and HTML files so an extremely simple web server is sufficient. Some optional parts are using PHP - but that's not a hard requirement for the runtime environment (but I guess 100% of the development web servers have it available). If there is a solution where Git should call a script it should be considered that the developers are using Linux, Windows and MacOS.Dramatist
H
7

I have a large body of experience working with AppCache-backed applications served by a Rails stack.

I've found the easiest thing by far is to not hardcode your version into your AppCache. You should be generating the file dynamically, and programatically generating a unique value for the version. Ideally, nobody should be introducing change to the manifests themselves, they should be introducing change to the inputs that programatically generate the file.

This isn't really unique to the AppCache. If you find where one specific line needs to be modified in virtually every commit, you probably shouldn't be hard-coding that line. It should be generated in some way, based on whatever changes in the repo prompt a change to that line.

Returning to the AppCache, I've found the easiest thing to do is:

  • in development, include the last-modified time of all the files in the appcache
  • in production, include the commit ID of the deployed Git commit

I have no idea what language you're using, but in the Rails world, my AppCache manifest looked something like the following. Nobody would ever have to change this file, they would only add or remove files from the @files array, which is managed in the controller that serves up this manifest:

CACHE MANIFEST

<% if Rails.env.development? %>
<% @cached_files.each do |file| %>
# <%= File.mtime(file) %>
<% end %>
<% else %>
# <%= `git rev-parse HEAD` %>
<% end %>

CACHE:
<% @cached_files.each do |file| %>
<%= file %>
<% end %>

NETWORK:
*

The first part, wrapped in Rails.env.development? outputs a series of comment lines, containing the last-modified time of every file included in the manifest. This means that, during development, the AppCache will be automatically expired whenever any file included in it is modified.

In production, the AppCache was expired when a new commit was deployed. This might be overkill for you; if you want to avoid needlessly expiring the AppCache of your users, you should do something more clever like hashing the files involved so that the cache expires when their contents change.

In the end, I wound up writing a small library for helping eliminate the repetitive bits of generating manifests. On the off chance you are using Rails, you might find it helpful: https://github.com/meagar/rails_appcache

Hombre answered 1/5, 2015 at 19:27 Comment(0)
G
1

Using CVS I could replace the timestamp with a $Id$ to let the program handle it automatically...

git can call git log's --format= handler on selected files when you're exporting code for deployment.

echo \*.meta  export-subst   >>.gitattributes

echo   '$Format:%cD$'   >test.meta   # there's lots of % codes available.
git add .; git commit -m-; 

git archive v2.3.6 | tar xCf /dir/that/appcache/is/watching -
Gelignite answered 7/5, 2015 at 0:32 Comment(0)
L
1

To emulate the CVS Keyword expansion in a plain Git checkout, you can use clean/smudge filters in Git, as explained here: Keyword Expansion.

Another option is to continue doing it the way you do, but define a custom merge driver that would remove the timestamps before the merge, perform the merge itself, and then re-add a new timestamp.

Layer answered 7/5, 2015 at 13:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.