Version Control

Document Sample
Version Control Powered By Docstoc
					 Version Control
Abstract Data Types



CS2023 Intersession 2007
           Outcomes: Version Control

   Applying RCS and SCCS, by Don Bolinger and Tan
    Bronson, on reserve in the library. Official RCS
    homepage: www.cs.purdue.edu/homes/trinkle/RCS/
   Version Control with Subversion, Ben Collins-Sussman,
    Brian W. Fitzpatrick, C. Michael Pilato
        http://svnbook.red-bean.com/
   After the conclusion of this section you should be able to
        Use RCS for personal version control for personal projects,
         and for collaboration on small projects
        Understand the principles of version control, so that other VC
         systems (CVS, Subversion, ...) can be mastered quickly
Source File Modification Cycle

        Create or Modify file


        Test the modified file



               Tests             no
             Succesful?


             yes
           Capture result
    Managing Source Code Files and
              Revisions
   Very important to be able to trace the changes
    made throughout the life of software
   May want to revert to a previous version of a file,
    in the event of a problem, or simply to compare
    versions
   Could create a backup of each version
   Better way is to have changes to a file tracked for
    us
       this is what version control does
   Modification Cycle with Archiving
Get existing revision        Modify

                              Test

                            Capture

                        Save modified file
                         as new revision
                                             Get existing revision

                                                                     Modify

                                                                      Test

                                                                     Capture

                                                              Save modified file
                                                               as new revision
             Goals of Source Control
   Ability to record file revisions
   Ability to retrieve previous file revisions
   Control over new revision creation
       sometimes need to modify older version
   Ability to record why a new revision was made
   Control of file modification
       Prevent conflicting modifications
   Easy access to all file revisions
       all revisions kept in a single file
                     SCCS, RCS, CVS
   There are many revision control systems
       SCCS
            available on most commercial Unices, but not on Linux
       RCS
            available on Linux and many BSD-based Unices
            very popular for personal version control and small projects
       CVS
            Built on top of RCS
            Manages groups of files and projects distributed over a
             network better than RCS
            Widely used for Open Source projects, however,...
                      Subversion
   Since August 2001
   Open source, all platforms
   Addresses limitations of CVS
   Features include:
       Directory versioning
       File renaming
       Plugs into Apache HTTP server
       ...
The Problem of File Sharing
Lock-Modify-Unlock Solution
        (eg. RCS)
Copy-Modify-Merge Solution
  (e.g., Subversion, CVS)
            Basics of Source Control
   So what do I archive?
       dynamic source files
       files that can't be reconstructed from other files
   What don't I archive
       derived files
       static (read-only files)
              Basics of Source Control
   Nomenclature
       revision
            each archived version of a source file
            associated with a revision number
       check-in
            adding a new revision to an archive file
       check-out
            removing new revision from an archive file
       working file
            source file revision checked out
              Basics of Source Control
   Source file revision numbers
       n.m. : major (n) and minor (m) revision numbers
       1.1, 1.2, ...
       Not necessarily the same as release numbers
   Source file revision storage
       only one revision of source file stored in literal form
       all others stored as differences (or diffs) from that
        single revision
            saves disk space!
               Basics of Source Control
   Log
       archive file also contains reasons why each revision
        was checked-in
   Steps in source control:
       create an archive file for each source file
       get a working file for reading
             source control system forces you to say explicitly when you
              intend to modify a file revision
             OK if you just want to compile or read
       get a working file for modification
              Basics of Source Control
   Steps in source control (cont'd):
       get a working file for modification
            if no one else has that revision locked, it will be locked in
             your name
            if someone else has that revision locked, you won't be
             allowed to lock it
            while lock is set, no one else can modify that revision
       comparing a working file to its archive file
       adding a working file to an archive file
              Basics of Source Control
   Steps in source control (cont'd):
       discarding a working file
            can't just delete working file
            need also to remove lock
       viewing history of an archive file
Basic Source Control Operations
                   Create an archive file

                    archive file exists

Get working file   Get working file         View working file
  for reading      for modification             history


                                            Compare working
                    no     keep             file to archive file
     Discard
    working file         changes
                              ?
                        yes
                      Add working
                            file
                      to archive file
                   archive file updated
                   RCS
ci        check in RCS revisions
co        check out RCS revisions
rcs       change RCS file attributes
rcsdiff   compare RCS revisions
rlog      print log messages
                    RCS Basics
1. Create an RCS directory in your development directory
2. Place the file under source control
   ci filename
3. Check out a file to make a change
   co -l filename
4. Edit the file as normal (emacs filename)
5. Compare working file to its RCS file
   rcsdiff filename
6. Check the file back in, creating a new version
   ci filename
          RCS initial check in: ci
% ci source.c
enter description, terminated with a
  '.' or end of file
>> Your description here
>> .
initial revision: 1.1
done
$
Working file checked in to archive and deleted
 RCS check out for modification: co
% co -l source.c
RCS/source.c,v --> source.c
revision 1.1
done
$
Latest revision checked out and stored in working file
    Compare working file to RCS file
% rcsdiff source.c
RCS file: source.c,v
retrieving version 1.1
diff -r1.1 source.c
.... (output from diff command)
   Can compare working file to any version:
% rcsdiff -r1.3 prog.c
   Can compare any version to any other
% rcsdiff -r1.2 -r1.3 prog.c
          Discard working file
% rcs -u source.c
RCS file: source.c,v
1.1 unlocked
done
Can then remove working file
% rm source.c
         RCS check in: ci
% ci source.c
new revison: 1.2; previous
 revision: 1.1
enter log message, terminated with
 a '.' or end of file
>> Your messsage here
>> .
done
$
RCS check in with implicit check out:
           ci -l and ci -u
% ci -l source.c
     Checks in source.c, and checks it out again with a
      lock
% ci -u source.c
     Checks in source.c, checks it out again without a
      lock
        View history of RCS file
% rlog source.c
RCS file: source.c,v
working file: source.c
head: 1.2
...
description:
...
revision 1.2
date: ..
your log message

revision 1.1
date: ...
initial revision (default log message)
    Basic Source Control Operations
                      Create an archive file   ci

                       archive file exists

co Get working file   Get working file          View working file rlog
     for reading      for modification              history
                      co -l
                                                Compare working
                      no        keep            file to archive file
        Discard
       working file           changes
                                                            rcsdiff
                                   ?
   rcs -u & rm               yes
                           Add working
                                 file          ci
                           to archive file
                      archive file updated
                     RCS Identifiers
   RCS can put special strings inside your files, to give
    version information
   These strings automatically get updated each time a new
    version is created
   Place string markers inside your source files (eg. in
    comments)
        $Id$
          Gives information on version no., date, author,...
        $Log$
          Displays entire file history with version description
        Version Control within emacs
   Use ctrl-x v v to register, check in/out
   Upon check-in, working file not erased, but
    changed to read-only.
       must check out in order to modify
   When checking in changes, enter log message
    into window, and terminate with crtrl-c ctrl-c
         Outcomes: Abstract Data Types

   Books on reserve:
      C for Java Programmers, Chapter 11 (11.5) and C
       Programming - a Modern Approach, Chapter 19
   After the conclusion of this section you should be able to
        Use opaque data types to create modules that implement
         abstract data types
            Stack Module
stack.h
#ifndef STACK_H
#define STACK_H

void make_empty(void);
int is_empty(void);
void push(int i);
int pop(void);

#endif
              Stack as array
#include "stack.h"
#define STACK_SIZE 100

static int contents[STACK_SIZE];
static int top = 0;

void make_empty(void){
  top = 0;
}
int is_empty(void){
  return top == 0;
}
static int is_full(void){
  return top == STACK_SIZE;
}
void push(int i){
  if (is_full()) {
    fprintf(stderr, "push: stack is full\n");
    exit(EXIT_FAILURE);
  }
  contents[top++] = i;
}
int pop(void) {
  if(is_empty()) {
    fprintf(stderr, "pop: stack is empty\n");
    exit(EXIT_FAILURE);
  }
  return contents[--top];
}
          Stack as Linked List
#include "stack.h"

typedef struct node {
  int data;
  struct node *next;
} NodeT;

static NodeT *top = NULL;
void make_empty(void)
{
  NodeT *next;
  while(top != NULL){
    next = top->next;
    free(top);
    top = next;
  }
}

int is_empty(void) {
  return top == NULL;
}
void push(int i) {
  NodeT *newNode;

    newNode = malloc(sizeof(NodeT));
    if (newNode == NULL) {
      fprintf(stderr, "push: stack is full\n");
      exit(EXIT_FAILURE);
    }
    newNode->data = i;
    newNode->next = top;
    top = newNode;
}
int pop(void) {
  NodeT *oldTop;
  int i;
  if(is_empty()) {
    fprintf(stderr, "pop: stack is empty\n");
    exit(EXIT_FAILURE);
  }
  oldTop = top;
  i = top->data;
  top = top->next;
  free(oldTop);
  return i;
  }
                 Stack Data Type
   Can only have one instance of preceding stack modules
   Need to create a stack type:
#include "stack.h"
int main()
{
  StackT s1, s2;
  new_stack(&s1);
  new_stack(&s2);
  push(&s1, 1);
  if (!is_empty(&s1))
    printf("%d\n", pop(&s1)); /* prints "1" */
  ...
}
stack.h     Stack Data Type
typedef struct node {
  int data;
  struct node *next;
} NodeT;
typedef struct {
  NodeT *top;
} StackT

void new_stack(StackT *s);
void make_empty(StackT *s);
int is_empty(const StackT *s);
void push(StackT *s, int i);
int pop(StackT *s);
       Stack Type as Linked List
#include "stack.h"

void new_stack(StackT *s){
  s->top = NULL;
}

void make_empty(StackT *s){
  NodeT *next;
  while(s->top != NULL){
    next = s->top->next;
    free(s->top);
    s->top = next;
  }
}
void push(StackT *s, int i) {
  NodeT *newNode;

    newNode = malloc(sizeof(NodeT));
    if (newNode == NULL) {
      fprintf(stderr, "push: stack is full\n");
      exit(EXIT_FAILURE);
    }
    newNode->data = i;
    newNode->next = s->top;
    s->top = newNode;
}
int is_empty(const StackT *s) {
  return s->top == NULL;
}
int pop(StackT *s) {
  NodeT *oldTop;
  int i;
  if(is_empty(s)) {
    fprintf(stderr, "pop: stack is empty\n");
    exit(EXIT_FAILURE);
  }
  oldTop = s->top;
  i = s->top->data;
  s->top = s->top->next;
  free(oldTop);
  return i;
  }
                     Stack Type
   The previous module allowed for multiple instances, but
    at the expense of information hiding!
   Nothing prevents a client from using a StackT
    variable as a structure:
StackT s1;

s1.top = NULL;
...
                  Opaque Data Type
   Incomplete structure definition:
        can define the type of a structure that hasn't been
         defined yet:
         typedef struct hidden *Visible;
        allows one to use the type Visible as a synonym for
         struct hidden *.
                   Opaque Data Type
   A data type is opaque because the client cannot access its
    full representation
        all the client knows is that it is represented by another
         data type
        client doesn't know that that data type is
   Consider module Mod that exports a data type called
    Abstract to the client
        mod.h defines a type Abstract as a pointer to a
         structure type called Concrete
     typedef struct Concrete *Abstract;
        there is no definition of Concrete in this file
      Client                 Implementation

  mod.h                         mod.c


typedef struct           struct Concrete {...};
  Concrete * Abstract;
                 Opaque Data Type
   The type Concrete is defined in an implementation
    file
   The client can use the type provided there are no
    attempts to dereference values of this type
     void f(Abstract p);
     is legal, but
     Abstract p;
     p->x;
        is illegal, because the type Abstract represents a
         pointer to the Concrete type, and the compiler has
         no information about this type
               Stack ADT Module
1) the type DataType of the data stored in the stack is
   known to the implementation
2) any number of stacks can be created; all stacks must have
   elements of the same type, DataType
3) the representation of the stack and stack elements are not
   visible to the client.

The first version will operate on a stack of integers.
             Stack ADT Header
#ifndef STACK_H
#define STACK_H

typedef int DataType;
typedef struct StackCDT *StackADT;

StackADT   Stack_new(void);
int        Stack_empty(StackADT s);
void       Stack_push(StackADT s, DataType i);
DataType   Stack_pop(StackADT s);
void       Stack_free(StackADT *s);

#endif
      Application of Stack ADT
#include "stack.h"

StackADT s1, s2;

s1 = Stack_new();
s2 = Stack_new();
Stack_push(s1, 1);
if (!Stack_empty(s1))
    printf("%d\n", Stack_pop(s1));
  ...
      Stack ADT Implementation
#include "stack.h"

typedef struct node {
  DataType d;
  struct node *next;
} NodeT;

typedef struct StackCDT {
  int count;
  NodeT *top;
} StackCDT;
        Stack ADT Implementation
StackADT Stack_new(void) {
  StackADT s;

    if((s = malloc(sizeof(StackCDT))) == NULL)
      exit(EXIT_FAILURE);
    s->count = 0;
    s->top = NULL;
    return s;
}

int Stack_empty(StackADT s) {
  return s->count == 0;
}
        Stack ADT Implementation
void Stack_push(StackADT s, DataType d) {
  NodeT *newNode;

    if ((newNode = malloc(sizeof(NodeT))) ==
    NULL) {
      fprintf(stderr, "push: stack is full\n");
      exit(EXIT_FAILURE);
    }
    newNode->d = d;
    newNode->next = s->top;
    s->top = newNode;
    s->count++;
}
        Stack ADT Implementation
DataType Stack_pop(StackADT s) {
  DataType d;
  NodeT *oldNode;

    oldNode = s->top;
    s->top = oldNode->next;
    s->count--;
    d = oldNode->d;
    free(oldNode);

    return d;
}
        Stack ADT Implementation
void Stack_free(StackADT *s) {
  NodeT *p, *q;

    for (p = (*s)->top; p; p = q) {
      q = p->next;
      free(p);
    }

    free(*s);
    *s = NULL
}
             Shallow and Deep Copy
   To push a new element d onto the stack:
      newNode->d = d;
   If newNode->d and d are pointers, this results in a
    shallow copy.
       If client deallocates variable pointed to by d then
        newNode->d becomes a dangling reference
           Shallow and Deep Copy
For a deep copy, use a callback function
  copyData_Stack()
For example, for strings and doubles:

DataType copyData_Stack(const DataType v) {
   return strdup(v);
}
DataType copyData_Stack(const DataType v) {
   return v;
}
char *strdup(const char *s) {
/* return a copy of s */
   char *kopy;    /* copy of s */

    if((kopy = calloc(strlen(s) + 1,
               sizeof(char))) == NULL)
       return NULL;
    strcpy(kopy, s);

    return kopy;
}
         Shallow and Deep Copy
We need another callback function, freeData_Stack()
For example, for string and doubles:

void freeData_Stack(DataType v) {
   free(v);
}

void freeData_Stack(DataType v) {
}
Stack ADT Header with Deep Copy
typedef char* DataType;
typedef struct StackCDT *StackADT;

DataType copyData_Stack(const Datatype v);
void freeData_Stack(DataType v);
StackADT Stack_new(void);
int      Stack_empty(StackADT s);
void     Stack_push(StackADT s, DataType i);
DataType Stack_pop(StackADT s);
void     Stack_free(StackADT s);
    Stack ADT Header with Deep Copy
   Implementation of callback functions must be
    provided by the client

DataType copyData_Stack(const Datatype v);
void freeData_Stack(DataType v);

   They are declared in the header file so that the
    implementation code can call them
     Stack ADT Implementation with
              Deep Copy
void Stack_push(StackADT s, DataType d) {
  NodeT *newNode;

    if ((newNode = malloc(sizeof(NodeT))) ==
    NULL) {
      fprintf(stderr, "push: stack is full\n");
      exit(EXIT_FAILURE);
    }
    newNode->d = copyData_Stack(d);
    newNode->next = s->top;
    s->top = newNode;
    s->count++;
}
    Stack ADT Implementation with
             Deep Copy
DataType Stack_pop(StackADT s) {
  DataType d;
  NodeT *oldNode;

    oldNode = s->top;
    s->top = oldNode->next;
    s->count--;
    d = copyData_Stack(oldNode->d);
    freeData_Stack(oldNode->d);
    free(oldNode);

    return d;
}
    Stack ADT Implementation with
             Deep Copy
void Stack_free(StackADT *s) {
  NodeT *p, q;

    for (p = (*s)->top; p; p = q) {
      q = p->next;
      freeData_Stack(p->d);
      free(p);
    }

    free(*s);
    *s = NULL
}