![]() |
|
| Daemon News Ezine | BSD News | BSD Mall | BSD Support Forum | BSD Advocacy | BSD Updates |
Managing websites using Unix Part FourCopyright © Nik Clayton nik@FreeBSD.org
1. Isn't this a little bit late?When I first started this series, I expected to be able to put out an article a month, for a total of six articles. Things were fine for the first three articles, and then my workload in real life went just a little bit mad. That's why this article is roughly nine months over due. Sorry about that. My thanks to the various people who have e-mailed me over the past nine months or so with praise for the previous articles. You all acted as a very strong incentive to continue, and I hope you find this article, and the rest in the series, very useful. To refresh your memory, the previous articles were:
2. IntroductionIf you have followed the previous articles you should now have a framework you can use to install the files in your work area (which you have been adding to your CVS repository as you go) in to the staging area. This framework includes a number of simple Makefiles, which do little more than list the names of the files which must be installed, and a more complex web.mk, which is included in to the smaller files, and contains most of the logic. This article explains how you can use make(1) to help automate converting files from one format to another. In particular, it describes how you can covert image files from JPEG format to GIF format automatically, and shows how this technique can also be used to store binary files safely in the CVS repository.
3. Pre-requisites
4. The problem: format conversionYou have created your website, and stored the contents in a CVS repository. In addition, you have created the appropriate framework to allow you to install your website in to the staging directory, which lets you preview your site and check that everything is working correctly. However, your website contains duplicate files, stored in different formats. Perhaps these are images, stored in GIF and JPEG format, or documents that you make available uncompressed, gzip'd, and bzip'd, or perhaps sound files in different audio formats, or... the list is endless. You could store all these duplicate files in your CVS repository. That is certainly the simplest and fastest solution, and if disk space is not an issue, is worth pursuing. For the majority of us disk space is an issue, and any approach that can be used to reduce it is a good one. To describe the problem more directly: you have one or more files that you want to make available in many different formats. Each of these distribution formats can be mechanically generated from the master format. When you install your website in to the staging area, you want to ensure that if any changes have been made to the file in its master format, that the copies stored in the distribution formats are updated. That last sentence is a big clue. Whenever you have a problem that involves regenerating one or more files whenever another file is changed you should start thinking about whether or not make(1) can help you solve the problem. 4.1. A practical exampleMany, many[2] websites come complete with a picture of their creator staring at you out of the top left corner of the screen, daring you to follow any of their links. As you should know, including very large images on a web page is frowned upon because it generally greatly increases the amount of time the page takes to download. Therefore it is very good practice to include a small thumbnail copy of the main image, and make this thumbnail a link to the larger picture. Typically, the small thumbnail is stored in GIF format, while the larger image is stored as a JPEG. In this example, the larger JPEG file is the master format and the smaller GIF file is the distribution format. This is because you get much better results scaling a large image down to a small size than you do scaling a small image up. So, what you should do is store the JPEG file in the repository. Our Makefile will contain rules to generate a GIF file from the JPEG. You probably have a suitable image that you can use to follow the rest of these examples. However, if you do not (and you want a quick laugh) feel free to use this JPEG picture of me. Plus, when you've finished with this article, it makes a handy target for a dart board. You should be in your work area for the rest of the examples in this article, with a copy of the files you have been editing from the previous articles checked out and ready to go. If you have been following the other examples then your CVS repository is located in ~/www/cvs-rep, and the working area is ~/www/mywebsite. % cd ~/www
% cvs -d ~/www/cvs-rep checkout mywebsite
% cd mywebsite
% ls
Makefile about.html index.html unix/ web.mk
Your directory contents might differ slightly, but that is what you should have if you have been following these articles. Now copy nik.jpeg (or another JPEG file of your choice) in to this directory. 4.2. Scaling the image by handBefore writing any code to automatically scale this image it is important to test the programs and methods at the command line. This is much easier to debug, and it is easier to experiment with additional effects that you might want to add. The steps that will be involved in converting the JPEG image to a smaller GIF file are;
These steps map nicely onto the commands that you need to run in order to carry out this task. The programs to do this are part of the netpbm and JPEG utilities that you should have installed earlier. If you have other command line software that you are familiar with then you can use that instead. But the examples are going to assume you are using these tools. The commands to produce a GIF file that contains 64 colours and is 25% of the original JPEG size are;
%
djpeg -pnm nik.jpeg > nik.pnm
% pnmscale .25 < nik.pnm > jkh-small.pnm
% ppmquant -fs 64 < jkh-small.pnm > jkh-smallcol.ppm
% ppmtogif < jkh-smallcol.ppm > nik.gif
Those commands are straightforward. .25 in the pnmscale command line is the scaling factor, in this case, 25%, while fs specifies Floyd-Steinberg error diffusion, which can give better results for some files. This is a more complex operation, and can take longer, so you can remove that option if you like. Notice that all these commands use STDIN and STDOUT for their input and output, which needs to be redirected to files as necessary. This means that you could string all these commands together in a pipeline, and avoid the need for temporary files.
% djpeg -pnm nik.jpeg | pnmscale .25 | \
ppmquant -fs 64 | ppmtogif > nik.gif
4.3. Makefile frameworkPutting these steps in to a Makefile is relatively straightforward, but there are a few traps for the unwary. To being with, you can just translate these instructions directly to a target. The target will have the name of the GIF image, and the dependency for the target is the JPEG image. This example also introduces a new make(1) variable.
nik.gif: nik.jpeg
djpeg -pnm ${.ALLSRC} | pnmscale .25 | \
ppmquant -fs 64 | ppmtogif > ${.TARGET}
.ALLSRC is set to the entire contents of the dependency list. In this case that is nik.jpeg. If you create a file with those lines in (call it image.mk) you will be able to automatically rebuild the GIF image from the JPEG.
% make -f image.mk nik.gif
djpeg -pnm nik.jpeg | pnmscale .25 | ppmquant -fs 64 | ppmtogif > nik.gif
ppmquant: making histogram...
ppmquant: 7454 colors found
ppmquant: choosing 64 colors...
ppmquant: mapping image to new colors...
ppmtogif: computing colormap...
ppmtogif: 64 colors found
% make -f image.mk nik.gif
% touch nik.jpeg
% make -f image.mk nik.gif
djpeg -pnm nik.jpeg | pnmscale .25 | ppmquant -fs 64 | ppmtogif > nik.gif
ppmquant: making histogram...
ppmquant: 7454 colors found
ppmquant: choosing 64 colors...
ppmquant: mapping image to new colors...
ppmtogif: computing colormap...
ppmtogif: 64 colors found
As you have just confirmed, nik.gif is only created if it does not exist, or if it does exist and nik.jpeg was modified more recently. Now that you can generate the GIF from the JPEG image, we need a mechanism to ensure that the images are installed when you run make install. Remember that the install target is written in web.mk, and requires some variables (specifically, DESTDIR, HTML, and possible SUBDIR) to have been set first. Also, remember the special _SUBDIRUSE target, which handles recursing down in to subdirectories as necessary. If you have been following these articles then your install target in web.mk should look like this.
install: _SUBDIRUSE
@[ -d ${DESTDIR} ] || ${MKDIR} -p ${DESTDIR}
@for htmlfile in ${HTML}; do \
${CP} -f $$htmlfile ${DESTDIR}/$$htmlfile; \
${CHMOD} 444 ${DESTDIR}/$$htmlfile; \
done
There is not too much wrong with this, and it will only take some minor changes to get it to work with the images. The first question to ask is ``How will install determine which files to install?'' This is easy to decide--we already have one variable, HTML, which contains a list of all the HTML files to install, so we can create two new variables, JPEG and GIF, and set these to contain the names of all the JPEG and GIF files to install. All that needs to be done is include these variables in the main for loop. For completeness' sake, we will change the name of the loop variable (currently htmlfile) to reflect this. Change the install target in web.mk to:
install: _SUBDIRUSE
@[ -d ${DESTDIR} ] || ${MKDIR} -p ${DESTDIR}
@for file in ${HTML} ${JPEG} ${GIF}; do \
${CP} -f $$file ${DESTDIR}/$$file; \
${CHMOD} 444 ${DESTDIR}/$$file; \
done
The second question to ask is ``How can we guarantee that the .GIF file will exist when we need to install it?'' A moment's thought should leave you realising that if you list the GIF files as dependencies for the install target, then make(1) will ensure that they exist (by running other rules, as necessary) before it runs the install target. Since the GIF files will all be listed in the GIF variable, you can just list the variable on the dependency line. So alter the definition and dependency line of install to;
install: ${GIF} _SUBDIRUSE
Go back to image.mk, and flesh it out with the following code:
#
# image.mk
#
# Show how to install HTML, JPEG, and GIF files
#
HTML= index.html
JPEG= nik.jpeg
GIF = nik.gif
DESTDIR=/tmp/images
nik.gif: nik.jpeg
djpeg -pnm ${.ALLSRC} | pnmscale .25 | \
ppmquant -fs 64 | ppmtogif > ${.TARGET}
.include "web.mk"
For the purposes of this test, the files will be installed in /tmp/images, although you can change that if you like. Make sure that index.html and nik.jpeg exist in the current directory, and that you have removed nik.gif. If you now try and use this Makefile to install your site, you should see the following;
% make -f image.mk install
djpeg -pnm nik.jpeg | pnmscale .25 | ppmquant -fs 64 | ppmtogif > nik.gif
ppmquant: making histogram...
ppmquant: 7454 colors found
ppmquant: choosing 64 colors...
ppmquant: mapping image to new colors...
ppmtogif: computing colormap...
ppmtogif: 64 colors found
[ -d /tmp/images ] || /bin/mkdir -p /tmp/images
If you recall, the various cp(1) commands are preceeded by a @ sign in web.mk, which is why they do not appear here. 5. Extending to support many GIF files (suffix rules)As you may have noticed with the last example, it is fine when all you have is one GIF file to create from one JPEG file, but what if you have a directory full of JPEG files and you want to ensure that they are all converted to GIF files? Your first thought (particularly if you read the previous article recently) might have been to move the rule that generated GIF files from JPEG files into its own target, and listed that target with .USE as a dependency. You could then list all your GIF files with this rule as a dependency, and let make(1) work its magic. Something like this, perhaps?
#
# Using .USE to convert images
#
JPEG= foo.jpeg bar.jpeg baz.jpeg
GIF = foo.gif bar.gif baz.gif
foo.gif: foo.jpeg _GIFJPEGUSE
bar.gif: bar.jpeg _GIFGPEJUSE
baz.gif: baz.jpeg _GIFJPEGUSE
_GIFJPEGUSE: .USE
djpeg -pnm ${.ALLSRC} | pnmscale .25 | \
ppmquant -fs 64 | ppmtogif > ${.TARGET}
That is not a bad idea. It is reusing code, which is good, and it is applying lessons learnt from the previous articles, which is also good. However, it is not the best approach. For example, see how you have to list each GIF file separately, and explicitly specify the JPEG file it depends on. It would be nice if make(1) could work out the dependencies for you. Fortunately, make(1) can, using what are called ``suffix rules'' A suffix rule is a body of code that you enter in to your Makefile that tells make(1) how to convert files with a filename that ends in one suffix (such as .jpeg) to files that end in another suffix (such as .gif). Any time that make(1) needs to create a file it looks to see if there is an explicit rule detailing how to create that file. For example, so far there has been an explicit rule detailing how to create nik.gif from nik.jpeg. If an explicit rule does not exist, make(1) starts looking at its list of suffix rules, to see if there are any instructions on how to create the file from another file with the same name, but a different suffix. If there are, make(1) uses that rule. In our situation, we want make(1) to determine that if there is not an explicit rule to create a GIF file, then it should check to see if there are any JPEG files with the same base name[3], and if one does exist, to use that the create the GIF file. Rather than try and build up a suitable suffix rule bit by bit, it is far simpler to show you the completed suffix rule, and then pick it apart. So, here is the complete suffix rule that tells make(1) how to convert our JPEG images to GIFs.
.SUFFIXES: .jpeg .gif
.jpeg.gif:
djpeg -pnm ${.ALLSRC} | pnmscale .25 | \
ppmquant -fs 64 | ppmtogif > ${.TARGET}
It really is that simple. .SUFFIXES: .jpeg .gif is how you tell make(1) that it has to know about these suffixes. It is not enough simply to list the rules in the Makefile, if the special .SUFFIXES target does not have the two suffixes as dependencies then nothing will happen. Notice how you have to include the dot as part of the suffix. The rule with the strange looking target is the suffix rule. The body of the rule is exactly as we have used before, but the rule target is a little strange. The target consists of the two suffixes (complete with the two dots, and with no spaces between them). The first suffix should be the name of the source suffix (i.e., the master format) and the second suffix should be the distribution format, as shown here. This is enough to make a slightly simpler image.mk, and a slightly more complicated web.mk. You can remove the explicit rule for nik.gif in image.mk, so you are left with;
#
# image.mk
#
# Show how to install HTML, JPEG, and GIF files
#
HTML= index.html
JPEG= nik.jpeg
GIF = nik.gif
DESTDIR=/tmp/images
.include "web.mk"
Then add the new suffix rule to web.mk, so you have;
#
# web.mk
#
CP= /bin/cp
CHMOD= /bin/chmod
MKDIR= /bin/mkdir
.SUFFIXES: .jpeg .gif
.jpeg.gif:
djpeg -pnm ${.ALLSRC} | pnmscale .25 | \
ppmquant -fs 64 | ppmtogif > ${.TARGET}
install: ${GIF} _SUBDIRUSE
@[ -d ${DESTDIR} ] || ${MKDIR} -p ${DESTDIR}
@for file in ${HTML} ${JPEG} ${GIF}; do \
${CP} -f $$file ${DESTDIR}/$$file; \
${CHMOD} 444 ${DESTDIR}/$$file; \
done
As before, make sure nik.gif has been removed, and re-run the install.
% make -f image.mk install
djpeg -pnm nik.jpeg | pnmscale .25 | ppmquant -fs 64 | ppmtogif > nik.gif
ppmquant: making histogram...
ppmquant: 7454 colors found
ppmquant: choosing 64 colors...
ppmquant: mapping image to new colors...
ppmtogif: computing colormap...
ppmtogif: 64 colors found
[ -d /tmp/images ] || /bin/mkdir -p /tmp/images
As you can see, there is no visible change. And because this code is now in web.mk, you can re-use it in any subdirectories of your web site which contain JPEG images that you wanted to convert to GIFs. Extending your Makefile to support converting multiple JPEG files to GIFs is now very easy. Either put some more JPEG files in your working directory, or make a few copies of nik.jpeg.
# cp nik.jpeg jkh1.jpeg
# cp nik.jpeg jkh2.jpeg
Then, update the JPEG= and GIF= lines in image.mk appropriately.
JPEG= nik.jpeg jkh1.jpeg jkh2.jpeg
GIF= nik.gif jkh1.gif jkh2.gif
Finally, re-run the last make.
% make -f image.mk
djpeg -pnm jkh1.jpeg | pnmscale .25 | ppmquant -fs 64 | ppmtogif > jkh1.gif
ppmquant: making histogram...
ppmquant: 7454 colors found
ppmquant: choosing 64 colors...
ppmquant: mapping image to new colors...
ppmtogif: computing colormap...
ppmtogif: 64 colors found
djpeg -pnm jkh2.jpeg | pnmscale .25 | ppmquant -fs 64 | ppmtogif > jkh2.gif
ppmquant: making histogram...
ppmquant: 7454 colors found
ppmquant: choosing 64 colors...
ppmquant: mapping image to new colors...
ppmtogif: computing colormap...
ppmtogif: 64 colors found
As you can see, the jkh1.gif and jkh2.gif files have been generated from their respective JPEG masters. Using these suffix rules, you can now store the JPEG files directly in the CVS repository, and only generate the GIF files when you build or install a copy of the web site. This cuts down on the repository size, at the expense of making builds take a little bit longer. 6. Storing binary files in the repository, and how suffix rules can help6.1. Binary files and the repository; possible problemsYou have probably started to think about how you are going to store our binary files (the JPEG images) in your CVS repository. This is a tricky subject, and one worth spending some time on. Obviously, binary files are different from ordinary text files. For one thing, you cannot perform meaningful diffs on them. You could not look at the binary differences between two JPEG files, and tell what the actual differences to the image were. This slightly reduces CVS' usefulness. It is also not possible to use CVS revision strings in binary files. I haven't mentioned these yet, but suffice to say that if CVS encounters special keywords in a file it is checking out, such as $Header: /usr/local/CVSROOT/ezine/articles/200004/ready/managing,v 1.9 2000/04/01 19:50:47 gsutter Exp $, or $Id: managing,v 1.9 2000/04/01 19:50:47 gsutter Exp $, it replaces the keyword with information about the file, such as its path, or the date and time it was checked out. This is useful information to have, particularly when you want to quickly see what revisions of files you have checked out. Despite this, storing binary files directly in the repository does have one big advantage. It's very easy to do, and you don't need to change any of your Makefiles to support it. So, knowing that you should definitely store either the binary files, or a mechanism for regenerating the binary files, in the repository, how do you go about doing that? 6.2. The simple way, -kbThe easiest way to bring binary files in to your CVS repository is to use -kb when you cvs add the file. This tells CVS that this is a binary file, and it turns off a few pieces of CVS functionality for this file in the process. For example, if CVS knows that a file is a binary file, it will not try and merge in any changes that have been made to that file if you do a cvs update. To add nik.jpeg to your repository, as a binary file (should you decide to do such a thing) you would run;
% cvs add -kb nik.jpeg
As I say, this is simple, easy, and does not give me the chance to write any more about suffix rules. So I will ignore it for the time being. Don't run that example. 6.3. The more interesting way, with uuencode(1)/uudecode(1)Suppose, however, that you prefer all the files in the repository to be text files (even if they should contain binary data). What do you do? This is already a solved problem, thanks to the pervasiveness of e-mail. E-mail over the Internet is not safe for binary files. There are too many systems out there with differing ideas of how many bits in each character are significant to make it feasible to safely e-mail binary files without first encoding them. This encoding process converts the binary files in to files that only use alphanumeric characters, making them safe for e-mail. Of course the size of a file that has been encoded in this way can be considerably larger than the original binary file, but that's the tradeoff you have to make. There are several possible methods you can use to encode files, but the grand-daddy of programs to do this is uuencode(1) (like uucp(1), I think the uu means "Unix to Unix", but I could be wrong). You use uuencode(1) to convert binary files to their text only equivalent, and you use uudecode(1) to convert the encoded text file back to the binary file. These programs are part of FreeBSD, and are almost certainly a part of whatever other Unix-like OS you are using. Using uuencode(1) is quite simple. Suppose you want to encode nik.jpeg so that it becomes a text file, and store the results in nik.uue.
% uuencode nik.jpeg nik.jpeg > nik.uue
If you investigate the nik.uue file, and work through the uuencode(1) manual page you will see how the conversion is done. The command line above is relatively simple. However, you might be wondering why nik.jpeg had to specified twice on the command line. The first occurence tells uuencode(1) the name of the file to convert. The second occurence tells uuencode(1) what this file should be called inside the encoded file. You can use this parameter to encode a file such that when it is decoded a different file is generated. If you were to run;
%
% uuencode nik.jpeg foo.jpeg > nik.uue
% uudecode nik.uue
You would see that the decoded file has been called foo.jpeg, because that is what was specified when encoding the file. To tell you the truth, I've never had a need for this feature, and when running uuencode(1) you just get in to the habit of typing the filename you are encoding twice. This is all very well, but how do we use it with make(1)? If you are thinking ahead, you should be able to see that if we have a .uue file, we can now construct a series of commands to convert that file first to its original JPEG format, and then use the rules we have already created to convert the JPEG file to a GIF file. A simple approach might look like this.
#
# Simple use of uudecode
#
# This is the default target
nik.gif: nik.jpeg
djpeg -pnm ${.ALLSRC} | pnmscale .25 | \
ppmquant -fs 64 | ppmtogif > ${.TARGET}
nik.jpeg: nik.uue
uudecode nik.uue
Put that code in a file called uue.mk (don't forgot about using TABs and not spaces in the rule body). Generate the nik.uue file if you have not already done so, then make sure that you have deleted nik.jpeg and nik.gif. Then run make(1) on uue.mk.
% uuencode nik.jpeg nik.jpeg > nik.uue
% rm nik.jpeg nik.gif
% make -f uue.mk
uudecode nik.uue
djpeg -pnm nik.jpeg | pnmscale .25 | ppmquant -fs 64 | ppmtogif > nik.gif
ppmquant: making histogram...
ppmquant: 7454 colors found
ppmquant: choosing 64 colors...
ppmquant: mapping image to new colors...
ppmtogif: computing colormap...
ppmtogif: 64 colors found
make(1) has had to do a little more work this time. nik.gif is the default target, and that file doesn't exist. make(1) can see that nik.jpeg must exist first, in order to create nik.gif, but that file does not exist either. But make(1) can see that it can generate nik.jpeg from nik.uue. which does exist. So make(1) first runs the body of nik.jpeg target, which generates nik.jpeg, which can then be used to generate nik.gif. You did not have to specify the direct relationship between nik.gif and nik.uue, make(1) inferred that from the rules you gave it. If you recall, we covered this back in the second article. We can use this information to update web.mk to teach it about .uue files, and create a suffix rule that will try and generate a .jpeg file from a .uue file as necessary. The changes are very simple. First, you have to replace the SUFFIXES line with this one.
SUFFIXES: .uue .jpeg .gif
As you can see, all this does is tell make(1) about a new suffix it can use. Then you have to add a suffix rule that tells make(1) how to go from .uue to .jpeg.
.uue.jpeg:
uudecode ${.ALLSRC}
Finally, you have to update the dependency line on the install target in web.mk.
install: ${GIF} ${JPEG} _SUBDIRUSE
You might be wondering why you now need to explicitly list ${JPEG}. Previously, you didn't, because it was assumed that all the JPEG files were part of the repository, and would therefore exist when you checked out a copy. However, now, that's not the case, as the JPEG files have to be created from the uuencoded files. If (and only if) every JPEG file is also used to generate a GIF file then there's no problem, and you would not need to add ${JPEG} as a dependency. This is because if all the GIF files are dependencies, then the build process for the GIF files will ensure that the JPEG files will exist as well--they have to, otherwise you can not create the GIF files from them. However, if you have some JPEG files that are only used as JPEG files, and are not listed as dependencies for any GIF files (for example, a foo.jpeg that was not used to generate foo.gif, but that still had to be installed) the JPEG file would not be created. By listing ${JPEG} as an explicit dependecy, make(1) will ensure that all the JPEG files exist before attempting to install them, rather than just the ones used to create GIF files. Were you expecting to add another variable to Makefile and web.mk, perhaps something like this?
UUE= nik.uue
There's absolutely no need. At the moment, the variables we have defined are used to determine which files should be installed. Because the .uue files are never installed, and because make(1) can work out the name of a .uue file based on the name of the .jpeg file it is required for, you do not need to explicitly list the UUE files. 6.4. A possible problem, and how to work around itSuppose you have one or more GIF files that are not generated from JPEG files, but that have to be stored in the repository. You might think that you can uuencode(1) these files, and create another suffix rule that describes how to create a GIF file from a UUE file. Something like this perhaps?
If you try that, you're in for a shock, because it doesn't work. You will see output like this.
% make
uudecode nik.uue
uudecode foo.uue
[ -d ../mystage ] || /bin/mkdir -p ../mystage
cp: nik.gif: No such file or directory
*** Error code 1
Stop.
You've been a victim of your own cleverness[4]. What's happened is that make(1) has tried to create nik.gif. Prior to adding the GIF to UUE suffix rule, the only way make(1) could do this was by first creating the JPEG file from the uuencoded file, and then converting the JPEG file to a GIF file - everything worked. However, now make(1) has a new rule that describes how GIF files can be generated directly from uuencoded files. make(1) applies this rule, and has assumed that nik.gif can be generated directly from nik.uue, without having to go through the intervening JPEG stage. This is obviously wrong, but make(1) doesn't notice until it tries to install nik.gif, which doesn't exist, because decoding nik.uue gives nik.jpeg instead. You can work around this problem, but it requires a bit of a kludge.
You can then remove the generated files, and re-run make(1).
# rm *.gif *.jpeg
# make
uudecode nik.jpeg-uue
djpeg -pnm nik.jpeg | pnmscale .25 | ppmquant -fs 64 | ppmtogif > nik.gif
ppmquant: making histogram...
ppmquant: 7454 colors found
ppmquant: choosing 64 colors...
ppmquant: mapping image to new colors...
ppmtogif: computing colormap...
ppmtogif: 64 colors found
uudecode foo.gif-uue
[ -d ../mystage ] || /bin/mkdir -p ../mystage
So first of all nik.jpeg-uue is decoded, and then converted to nik.gif, and then foo.gif-uue is just decoded, to produce foo.gif. As I say, it's a bit of a kludge, but it works. 6.5. Extending this to other file formatsYou can use this approach for any binary data you might want to sore in the repository, regardless of the format. The only steps you have to follow each time you add a new format are:
7. In the next article...... we shall be looking at methods for copying your web site from the staging area (which, if you recall, is your local copy of the web site for testing purposes) to the live site area. Hopefully that will be next month, but I'm not going to promise anything... Notes
|