/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 1, or (at your option)
** any later version.

** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.

** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
 * Author : Kirill Müller <mail@kirill-mueller.de> --- February 2006
 */

/*
 * DiffParse.cpp : parse the CVS diff output
 */

#include "stdafx.h"

#include <stdio.h>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif

#ifdef TARGET_OS_MAC
#	include <unistd.h>
#endif /* TARGET_OS_MAC */

#include "DiffParse.h"
#include "AppConsole.h"
#include "getline.h"

#ifdef WIN32
#	ifdef _DEBUG
#	define new DEBUG_NEW
#	undef THIS_FILE
	static char THIS_FILE[] = __FILE__;
#	endif
#endif /* WIN32 */

//////////////////////////////////////////////////////////////////////////
// 	CCvsDiffConsole

CCvsDiffConsole::CCvsDiffConsole(MultiFiles* mf, const char* dir)
{
	m_mf = mf;
	m_state = AFTER_NL;
	m_dir = dir;
}

long CCvsDiffConsole::cvs_out(const char* txt, long len)
{
	static const char* INDEX = "Index: ";
	static const int INDEX_LEN = strlen(INDEX);
	
	int lenOut = 0;

	while( len ) 
	{
		if( m_state == AFTER_NL && len >= INDEX_LEN )
		{
			if( !strncmp(txt, INDEX, INDEX_LEN) )
			{
				m_state = AFTER_INDEX;
				txt += INDEX_LEN;
				len -= INDEX_LEN;
				continue;
			}
		}

		if( *txt == '\r' || *txt == '\n' )
		{
			if( m_state == AFTER_INDEX )
			{
				::cvs_outstr(m_fileName.c_str(), m_fileName.length());
				::cvs_outstr("\n", 1);
				
				lenOut += m_fileName.length() + 1;
				
				if( !m_mf->NumDirs() )
					m_mf->newdir(m_dir.c_str());

				m_mf->newfile(m_fileName.c_str());
				m_fileName.erase();
			}

			m_state = AFTER_NL;
			txt++;
			len--;
		}
		else 
		{
			if( m_state == AFTER_INDEX )
			{
				char sAppend[2] = { txt[0], 0 };
				
				m_fileName += sAppend;
			}
			else
			{
				m_state = NONE;
			}

			txt++;
			len--;
		}
	}
	
	return lenOut;
}

long CCvsDiffConsole::cvs_err(const char* txt, long len)
{
	cvs_errstr(txt, len);
	
	return len;
}

/*!
	Launch a CVS diff command, parse the output, add the changed files to a MultiFiles collection
	\param dir Directory
	\param args Arguments
	\param files Differing files
	\return true on success, false otherwise
*/
bool CvsDiffParse(const char* dir, const CvsArgs& args, MultiFiles& files)
{
	CCvsDiffConsole myConsole(&files, dir);
	
	const int ret = launchCVS(dir, args.Argc(), args.Argv(), &myConsole);

	return ret != 2;
}
