Index: openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-advanced.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-advanced.xml,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-advanced.xml 30 Mar 2003 20:31:47 -0000 1.1.2.1 @@ -0,0 +1,96 @@ + + Advanced Topics + + This section is a work in progress. + + + by Joel Aufrecht + + + + Overview + This tutorial covers topics which are not essential to + creating a minimal working package. Each section can be used + independently of all of the others; all sections assume that + you've completed the basic tutorial. + + + How to enforce security so that users can't + change other users records + + How to use the content management tables so that ... what? + How to make your package searchable with OpenFTS/Oracle + How to make your package send email notifications + How to prepare pagelets for inclusion in other pages + How and when to put procedures in a tcl procedure library + How to add general_comments to your pages + More on ad_form - data validation, other stuff. + (plan to draw from Jon Griffin's doc) + How and when to implement caching + partialquery in xql + How to use the html/text entry widget to get the + "does this look right" confirm page + APM package dependencies + + + + + General_comments + You can track comments for any ACS Object. Here we'll track + comments for notes. On the notes.tcl/adp pair, which is used to + display individual notes, we want to put a link to add comments at + the bottom of the screen. If there are any comments, we want to + show them. + First, we need to generate a url for adding comments. In notes.tcl: + +set comment_add_url "[general_comments_package_url]comment-add?[export_vars { + { object_id $note_id } + { object_name $title } + { return_url "[ad_conn url]?[ad_conn query]"} +}]" + + This calls a global, public tcl function that the + general_comments package registered, to get its url. You then + embed in that url the id of the note and its title, and set the + return_url to the current url so that the user can return after + adding a comment. + Now we need to create html that shows any existing comments. + We do this with another general_comments function: + set comments_html [general_comments_get_comments + -print_content_p 1 $note_id] + First, we pass in an optional parameter that that says to actually + show the contents of the comments, instead of just the fact that + there are comments. Then you pass the note id, which is also the + acs_object id. + Now we put our two new variables in the notes.adp + page. + <a href="@comment_add_url@">Add a comment</a> +@comments_html@ + + + + Prepare the package for distribution. + Browse to the package manager. Click on + tutorialapp. + Click on Generate a distribution file + for this package from the + filesystem. + + Click on the file size + (37.1KB) + after the label Distribution + File: and save the file to + /tmp. + + The publish point for new packages should be + fixed. + + + + + + Index: openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-db.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-db.xml,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-db.xml 30 Mar 2003 20:31:47 -0000 1.1.2.1 @@ -0,0 +1,283 @@ + + Setting Up Database Objects + + + by Joel Aufrecht + + + + Code the data model + We create all database objects with scripts in the + samplenote/sql/ directory. All + database scripts are database-specific and are thus in either + the samplenote/sql/oracle or + samplenote/sql/postgresql. + Packages can support Oracle, PostgreSQL, or both. + The first file is + samplenote-create.sql. The + package manager requires a file with the name + packagekey-create.sql, + which it will run automatically when the package in installed. + This file should create all tables and views. + + Our package is going to store all of its information in + one table. It takes more than just a CREATE + TABLE command, however, because we want to + integrate our table with the OpenACS system. By making each + record in our table an OpenACS object, we gain access to the + permissions system as well as some metadata. The downside is + that our table creation code must include several functions and + stored procedures and is fairly complicated even for a simple + table. A listing is provided below for you to cut and paste. + Comments are located within the source code, with each comment + preceeding the relevant code. + + First, create the necessary subdirectories and add them + cvs as you go. + [service0@yourserver samplenote]$ mkdir sql +[service0@yourserver samplenote]$ cvs add sql +Directory /cvsroot/service0/packages/samplenote/sql added to the repository +[service0@yourserver samplenote]$ cd sql/ +[service0@yourserver sql]$ mkdir postgresql +[service0@yourserver sql]$ cvs add postgresql +Directory /cvsroot/service0/packages/samplenote/sql/postgresql added to the repository +[service0@yourserver sql]$ cd postgresql/ +[service0@yourserver postgresql]$ emacs samplenote-create.sql + Paste this into the file and save and close. +
+ Database Creation Script + -- +-- packages/samplenote/sql/postgresql/samplenote-create.sql +-- +-- @author rhs@mit.edu +-- @creation-date 2000-10-22 +-- @cvs-id $Id: tutorial-db.xml,v 1.1.2.1 2003/03/30 20:31:47 joela Exp $ +-- +-- + +/* We create a temporary function 'inline_0' which we use to +create an ACS Object Type. Each record in our package is a +'samplenote', and each samplenote will be an ACS Object. By making +our records ACS objects, we gain access to the permissions model and +other meta-functions. Each 'samplenote' record will have a matching +record in acs_objects. In general, you should make a table an ACS +Object Type if you expect to apply permissions directly at that level. */ + +create function inline_0 () +returns integer as ' +begin + PERFORM acs_object_type__create_type ( + ''samplenote'', -- object_type + ''Sample Note'', -- pretty_name + ''Sample Notes'', -- pretty_plural + ''acs_object'', -- supertype + ''samplenote'', -- table_name + ''note_id'', -- id_column + null, -- package_name + ''f'', -- abstract_p + null, -- type_extension_table + ''samplenote__name'' -- name_method + ); + return 0; +end;' language 'plpgsql'; +select inline_0 (); +drop function inline_0 (); + +/* We create the table. Each constraint is named to make it easier to +identify during debugging. The note_id is identical to the object +id.*/ + +create table samplenote ( + note_id integer constraint samplenote_fk + references acs_objects(object_id) + constraint samplenote_pk + primary key, + title varchar(255) + constraint samplenote_title_nn + not null, + body varchar(1024) +); + +/* Since each record is also an Object, we make a creation function +that will create an object and then use the object id to create a +record in our table. The function also takes several optional input +variables. Creation date will default to now; creation user should be +the user id that will own the object; creation ip is optional; context +id should usually be the package id, which will be explained later.*/ + +create function samplenote__new (varchar,varchar,timestamp,integer,varchar,integer) +returns integer as ' +declare + p_title alias for $1; + p_body alias for $2; + p_creation_date alias for $3; + p_creation_user alias for $4; + p_creation_ip alias for $5; + p_context_id alias for $6; + v_samplenote_id int; +begin + v_samplenote_id := acs_object__new ( + null, + ''samplenote'', + p_creation_date, + p_creation_user, + p_creation_ip, + p_context_id + ); + insert into samplenote + (note_id, title, body) + values + (v_samplenote_id, p_title, p_body); + PERFORM acs_permission__grant_permission( + v_samplenote_id, + p_owner_id, + ''admin'' + ); + return v_samplenote_id; +end;' language 'plpgsql'; + +/* The __delete function deletes a record and all related overhead. */ + +create function samplenote__delete (integer) +returns integer as ' +declare + p_samplenote_id alias for $1; +begin + delete from acs_permissions + where object_id = p_samplenote_id; + delete from samplenote + where note_id = p_samplenote_id; + raise NOTICE ''Deleting samplenote...''; + PERFORM acs_object__delete(p_samplenote_id); + return 0; +end;' language 'plpgsql'; + +/* When we created the acs object type above, we specified a +'name_method'. This is the name of a function that will return the +name of the object. This is a convention ensuring that all objects +can be identified. Now we have to build that function. In this case, +we'll return a field called title as the name. */ + +create function samplenote__name (integer) +returns varchar as ' +declare + p_samplenote_id alias for $1; + v_samplenote_name samplenote.title%TYPE; +begin + select title into v_samplenote_name + from samplenote + where samplenote_id = p_samplenote_id; + return v_samplenote_name; +end; +' language 'plpgsql'; + +
+ Create a database file to drop everything if the package + is uninstalled. + [service0@yourserver postgresql]$ emacs samplenote-drop.sql +
+ Database deletion script + -- packages/samplenote/sql/samplenote-drop.sql +-- drop script +-- + +/* This script removes from the database everything associated with +our table. */ + +--drop functions +drop function samplenote__new (varchar,varchar,timestamp,integer,varchar,integer); +drop function samplenote__delete (integer); +drop function samplenote__name (integer); + +--drop permissions +delete from acs_permissions where object_id in (select note_id from samplenote); + +--drop objects +create function inline_0 () +returns integer as ' +declare + object_rec record; +begin + for object_rec in select object_id from acs_objects where object_type=''samplenote'' + loop + perform acs_object__delete( object_rec.object_id ); + end loop; + return 0; +end;' language 'plpgsql'; + +select inline_0(); +drop function inline_0(); + +--drop table +drop table samplenote; + +--drop type +select acs_object_type__drop_type( + 'samplenote', + 't' + ); +
+ Add the database files to cvs. + [service0@yourserver postgresql]$ cvs add *.sql +cvs add: scheduling file `samplenote-create.sql' for addition +cvs add: scheduling file `samplenote-drop.sql' for addition +cvs add: use 'cvs commit' to add these files permanently +[service0@yourserver samplenote]$ cvs commit -m "new database files" +cvs commit: Examining . +cvs commit: Examining sql +cvs commit: Examining sql/postgresql +cvs commit: Examining www +cvs commit: Examining www/doc +cvs commit: Examining www/doc/xml +RCS file: /cvsroot/service0/packages/samplenote/sql/postgresql/samplenote-create.sql,v +done +(many lines omitted) +done +[service0@yourserver samplenote]$ + Now run the create script manually to add your tables and functions. + [service0@yourserver samplenote]$ cd sql/postgresql/ +[service0@yourserver postgresql]$ psql -f samplenote-create.sql +CREATE + inline_0 +---------- + 0 +(1 row) + +DROP +psql:samplenote-create.sql:51: NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index 'samplenote_pk' for table 'samplenote' +psql:samplenote-create.sql:51: NOTICE: CREATE TABLE will create implicit trigger(s) for FOREIGN KEY check(s) +CREATE +CREATE +CREATE +CREATE +[service0@yourserver postgresql]$ + If there are errors, use them to debug the sql file and try again. Once you get the same output as shown above, test the drop script: + [service0@yourserver postgresql]$ psql -f samplenote-drop.sql +DROP +DROP +DROP +DELETE 0 +CREATE + inline_0 +---------- + 0 +(1 row) + +DROP +psql:samplenote-drop.sql:33: NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "acs_objects" +psql:samplenote-drop.sql:33: NOTICE: DROP TABLE implicitly drops referential integrity trigger from table "acs_objects" +DROP + acs_object_type__drop_type +---------------------------- + 0 +(1 row) + +[service0@yourserver postgresql]$ + Once both scripts are working without errors, run the create script one last time and proceed. +
+
+ Index: openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-debug.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-debug.xml,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-debug.xml 30 Mar 2003 20:31:48 -0000 1.1.2.1 @@ -0,0 +1,83 @@ + + Debugging and Automated Testing + + This section is a work in progress. + + + + by Joel Aufrecht + + + Debugging + + PostgreSQL + You can work directly with the database to do debugging + steps like looking directly at tables and testing stored + procedures. Start emacs. Type + M-x sql-postgres. Press enter for + server name and use openacs-dev for + database name. You can use C-(up arrow) and C-(down arrow) + for command history. + + + + Watching the server log + +NOTE: explain how to add tcl to directly write your own log output + To set up real-time monitoring of the Aolserver error + log, type less /usr/local/aolserver/log/openacs-dev-error.log + F to show new log entries in real time (like tail -f) +C-c to stop and F to start it up again. +G goes to the end. +? searches backward +/ searches forward. + + + + + + + + Manual testing + Make a list of basic tests to make sure it works + + + Test Num + Action + Expected Result + + 001 + Browse to the index page while not logged in and + while one or more notes exist. + No edit or delete or add links should appear. + + + 002 + Browse to the index page while logged in. An Edit + link should appear. Click on it. Fill out the form and + click Submit. + The text added in the form should be visible on the + index page. + + + Other things to test: try to delete someone else's + note. Try to delete your own note. Edit your own note. + Search for a note. + + + + Write automated tests + + Create the automated tests for the package. + (Forthcoming.) + + + + + + + Index: openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-extended.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/developers-guide/Attic/tutorial-extended.xml,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-extended.xml 30 Mar 2003 20:31:48 -0000 1.1.2.1 @@ -0,0 +1,88 @@ + + OpenACS &version; Package Tutorial + + + by Joel Aufrecht + + + + Overview + How to create a package. Includes + + + How to use the APM to start a new + package + + How to write documentation, including self-documenting code + How to set up the database tables and procedures for your new package, including: + + How to create automated install/uninstall/upgrade scripts + How and when and why to use acs_objects + How to use stored procedures for __new, __delete, and __name stored procedures + How to use the content management tables so that ... what? + + + How to make your package searchable with OpenFTS/Oracle + How to make your package send email notifications + How to use tcl/adp pairs to present pages, + including + + How to use ad_page_contract + How to use the template system + How to prepare pagelets for inclusion in other pages + + + How and when to put procedures in a tcl procedure library + How to add general_comments to your pages + How to use a single ad_form to make a page that shows insert/edit forms, validates data, and does the database work. (plan to draw from Jon Griffin's doc) + How to add automated regression testing to your packages + How and when to implement caching + How to isolate database code for portability + How to use the html/text entry widget to get the "does this look + right" confirm page + How to debug; how to output to log + APM package dependencies + + + + + General_comments + blah blah introduction (steal text from gc docs) + You can track comments for any ACS Object. Here we'll track + comments for notes. On the notes.tcl/adp pair, which is used to + display individual notes, we want to put a link to add comments at + the bottom of the screen. If there are any comments, we want to + show them. + First, we need to generate a url for adding comments. In notes.tcl: + +set comment_add_url "[general_comments_package_url]comment-add?[export_vars { + { object_id $note_id } + { object_name $title } + { return_url "[ad_conn url]?[ad_conn query]"} +}]" + + This calls a global, public tcl function that the + general_comments package registered, to get its url. You then + embed in that url the id of the note and its title, and set the + return_url to the current url so that the user can return after + adding a comment. + Now we need to create html that shows any existing comments. + We do this with another general_comments function: + set comments_html [general_comments_get_comments + -print_content_p 1 $note_id] + First, we pass in an optional parameter that that says to actually + show the contents of the comments, instead of just the fact that + there are comments. Then you pass the note id, which is also the + acs_object id. + Now we put our two new variables in the notes.adp + page. + <a href="@comment_add_url@">Add a comment</a> +@comments_html@ + + + + Index: openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-pages.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-pages.xml,v diff -u -N --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-pages.xml 30 Mar 2003 20:31:48 -0000 1.1.2.1 @@ -0,0 +1,314 @@ + + Creating Web Pages + + + by Joel Aufrecht + + + + Build the "Index" page + Each user-visible page in your package has, typically, + three parts. The xql file contains any database queries, the + tcl file holds the procedural logic for the page and does things + like check permissions, invoke the database queries, and modify + variables, and the adp page + holds html. The default page in any directory is + index, so we'll build that + first, starting with the tcl file: + + [service0@yourserver samplenote]$ cd /web/service0/packages/samplenote/www +[service0@yourserver www]$ emacs index.tcl + Paste this into the file. There are several things to +note about the file: + + The page begins with an + ad_page_contract function. + This is where we declare the input and output variables and + their types and restrictions. It's also where we document the + page, including descriptions of the parameters and return. + + + We have one input variable, + orderby, which is optional + and defaults to title. + + + We have one output variable, table_html + + + We populate the table_html variable with a function call, ad_table, which does most of the work of generating an html table from a database recordset. We pass it several parameters: + + + -Torderby $orderby + + If the user has selected a column for sorting, this passes that information to the function. + + + + notes_query + + This is the name of the SQL query that we'll put in the xql file. + + + + { *SQL* } + + This is a dummy placeholder. It's possible to put sql directly in the tcl file, but this is deprecated because it's harder to make portable. + + + + $table_def + + Here we pass in the variable we just constructed; it contains a list of column names and display titles. + + + + + + + ad_page_contract { + This is the main page for the package. It displays all of the Sample Notes\ and provides links to edit them and to create new Notes. + + @author rhs@mit.edu + @creation-date 2000-10-23 + @cvs-id $Id: tutorial-pages.xml,v 1.1.2.1 2003/03/30 20:31:48 joela Exp $ + @param orderby indicates when the user clicks on a column to order by that \column + @return table_html preformatting html table constructed by querying the sam\plenotes table + +} { + {orderby:optional {title}} +} -properties { + table_html +} +# define the columns in the table +set table_def { + {title "Note"} + {body "Contents"} + {edit "" {} {<td><a href="note-edit?note_id=$note_id">Edit</a></td>}} + {delete "" {} {<td><a href="note-delete?note_id=$note_id">Delete</a></td>}} +} + +# construct an html table from the samplenotes database table +set table_html [ad_table -Torderby $orderby notes_query { *SQL* } $table_def] + Now put the database query into a separate file. If the + database query is exactly the same for Oracle and PostgreSQL, it + can go into a file with the same name as the tcl file but an xql + extension, e.g., index.xql. If + it is database-specific, it goes in + index-oracle.xql or + index-postgresql.xql. The + format is the same in each case, an XML structure that contains + the SQL query. Create the file now. + [service0@yourserver www]$ emacs index.xql + Note that the + name parameter of the + fullquery tag exactly matches + the SQL query name specified in the + ad_table call. Also, the SQL query ends with a tcl function call that generates a SQL ORDER BY clause using several TCL variables. + <?xml version="1.0"?> +<queryset> + <fullquery name="notes_query"> + <querytext> + select note_id, + title, + body + from samplenote + [ad_order_by_from_sort_spec $orderby $table_def] + </querytext> + </fullquery> +</queryset> + Now we create the user-visible page. + [service0@yourserver www]$ emacs index.adp + The first line indicates that this page should be rendered within the the master template, which defaults to /web/service0/www/default-master. The second line passes a title variable to the master template. The third line inserts the contents of the variable table_html. The last line is a link to a page we haven't created yet. + <master> +<property name="title">Sample Notes</property> +@table_html@ +<p><a href="note-edit">Add a note</a></p> + + + Add files to APM + Before we can test these files, we have to notify the package manager that they exist. (To be precise, the tcl and adp will work fine as-is, but the xql file will not be recognized until we tell the APM about it.). + + Go to http://yourserver.test:8000/acs-admin/apm + + Click on the samplenote link + + Click Manage file information + + + Click Scan the packages/samplenote directory for additional files in thispackage + + Click add checked files + + + Now that the pages are in the APM, check to make sure that the self-documenting code is working. + + Browse to http://yourserver:8000/api-doc/ + + Click # Notes (Sample Application) 0.1d + + Click Content Pages + + Click index.tcl and examine the results. + + + + + Test the index page + Go to http://192.168.0.2:8000/samplenote/. You should see something like this: + +Sample Notes +Your Workspace : Main Site : Sample Note + +No data found. + +foo@yourserver.test + + Since our table is empty, it's a pretty boring page. So next we'll make it possible to add records. + If you get any other output, such as an error message, skip to . Note also that, while tcl and adp pages update automatically, xql pages get cached. So if you change an xql page, the change won't take effect unless you restart the server, reload the package via the APM, or put a watch on the file in the APM file list. With a watch, which lasts until the next service restart, the file will be updated each time it is changed on disk. + + + Add the add/edit page + We'll create a single page to handle both adding and editing records. First, create the tcl: + [service0@yourserver www]$ emacs note-edit.tcl + The page takes a single, optional input parameter, note_id. If it's present, logic within ad_form will assume that we're editing an existing record. We check user_id with ad_maybe_redirect_for_registration, which will redirect to the login page (with an automatic return path to bring them back after login or registration) if the visitor isn't logged in. Then we call ad_form, specifying the primary key of the table, the fields we want to edit, and functions for insert and update. + ad_page_contract { + Simple add/edit form for samplenote. +} { + note_id:optional +} +set user_id [ad_maybe_redirect_for_registration] + +ad_form -name note -form { + note_id:key + {title:text + {label "Title"} + } + {body:text(textarea) + {label "Body"} + } +} -select_query_name note_query -new_data { +db_1row do_insert { *SQL* } +} -edit_data { +db_dml do_update { *SQL* } +} -after_submit { +ad_returnredirect "index" +ad_script_abort +} + Next, we create the database functions. + [service0@yourserver www]$ emacs note-edit.xql + <?xml version="1.0"?> +<queryset> + <fullquery name="do_insert"> + <querytext> + select samplenote__new(:title, :body,null,:user_id,null,null) + </querytext> + </fullquery> + <fullquery name="do_update"> + <querytext> + update samplenote + set title = :title, + body = :body + where note_id = :note_id + </querytext> + </fullquery> + <fullquery name="note_query"> + <querytext> + select title, + body + from samplenote + where note_id = :note_id + </querytext> + </fullquery> +</queryset> + And now the user-visible page: + [service0@yourserver www]$ emacs note-edit.adp + <master> +<formtemplate id="note"></formtemplate> + + Go to the APM as before and scan for new files and add your new work. Then test all this by going to the package home page and adding and editing a few records. + + + A Deletion page + Now we need a way to delete records. We'll create a recursive confirmation page. + [service0@yourserver www]$ emacs note-delete.tcl + This page requires a note_id to determine which record should be deleted. It also looks for a confirmation variable, which should initially be absert. If it is absent, we create a form to allow the user to confirm the deletion. The form calls the same page, but with hidden variables carrying both note_id and confirm_p. + ad_page_contract { + A page that gets confirmation and then delete notes. + + @author joel@aufrecht.org + @creation-date 2003-02-12 + @cvs-id $Id: tutorial-pages.xml,v 1.1.2.1 2003/03/30 20:31:48 joela Exp $ +} { + note_id:integer + confirm_p:optional +} + +set title "Delete Note" + +if {[exists_and_not_null confirm]} { + # if confirmed, call the database to delete the record + db_1row do_delete { *SQL* } + ad_returnredirect "index" +} else { + # if not confirmed, display a form for confirmation + set note_name [db_string get_name { *SQL }] + set title "Delete $note_name" + template::form::create note-del-confirm + template::element::create note-del-confirm note_id -value $note_id -widget \hidden + template::element::create note-del-confirm confirm_p -value 1 -widget hidden +} + Now the database calls: + [service0@yourserver www]$ emacs note-delete.xql + <?xml version="1.0"?> +<queryset> + <fullquery name="do_delete"> + <querytext> + select samplenote__delete(:note_id) + </querytext> + </fullquery> + <fullquery name="get_name"> + <querytext> + select samplenote__name(:note_id) + </querytext> + </fullquery> +</queryset> + And the adp page: + [service0@yourserver www]$ emacs note-delete.adp + <master> +<property name="title">@title@</property> +<h2>@title@</h2> +<formtemplate id="note-del-confirm"></formtemplate> +</form> + Now test it by adding the new files in the APM and then deleting a few samplenotes. + + + Adding files to cvs + Put your new work into source control. + [service0@yourserver www]$ cvs add *.adp *.tcl *.xql +cvs add: cannot add special file `CVS'; skipping +cvs add: doc/CVS already exists +cvs add: scheduling file `index.adp' for addition +cvs add: scheduling file `index.tcl' for addition +cvs add: scheduling file `index.xql' for addition +cvs add: scheduling file `note-delete.adp' for addition +cvs add: scheduling file `note-delete.tcl' for addition +cvs add: scheduling file `note-delete.xql' for addition +cvs add: scheduling file `note-edit.adp' for addition +cvs add: scheduling file `note-edit.tcl' for addition +cvs add: scheduling file `note-edit.xql' for addition +cvs add: use 'cvs commit' to add these files permanently +[service0@yourserver www]$ cvs commit -m "new work" +/cvsroot/service0/packages/samplenote/www/note-edit.xql~,v <-- note-edit.xql +(many lines omitted) +initial revision: 1.1 +done +[service0@yourserver www]$ + + + +